リストを区切り文字を使用して1行に変換

リストを区切り文字を使用して1行に変換

次の形式でIPアドレス(ペイロード)のリストを取得する必要があります。

 134.27.128.0
 111.245.48.0
 109.21.244.0

途中でパイプ(IPで作成)を使用してこの形式に変換します。

134.27.128.0 | 111.245.48.0 | 109.21.244.0 | 103.22.200.0/22

検索と置換コマンドのようですが、sed正しく機能しません。

答え1

sedを使う有名なSedキップの説明、パート1::39. 行がバックスラッシュ「\」で終わったら、次の行に追加します。(ここではバックスラッシュに関する部分を無視し、\n改行文字を必須区切り文字|に置き換えます。)

sed -e :a -e '$!N; s/\n/ | /; ta' mydoc > mydoc2

で生産されなければならないmydoc2

134.27.128.0 |  111.245.48.0 |  109.21.244.0

答え2

163MiBIPこれらのいくつか(+いくつかの選択肢)がかなり大きなファイル(1行に1つ、〜1,300万行)でどのようにすばやく機能するのか疑問に思います。

wc -l < iplist
13144256

結果(sync; echo 3 > /proc/sys/vm/drop_caches各コマンドの後;数時間後に逆の順序でテストを繰り返しましたが、違いはわずかでした。また、使用していることに注意してくださいgnu sed):

スチールドライバーa:
非常に遅い。 2分ほど待ってから中止します。したがって、結果はありません。

クエンラム:

awk 'FNR!=1{print l}{l=$0};END{ORS="";print l}' ORS=' | ' iplist

real    0m3.672s

perl -pe 's/\n/ | / unless eof' iplist

real    0m12.444s

マックサイフ:

paste -d\  /dev/null iplist /dev/null | paste -sd\| - 

real    0m0.983s

ゼチル:

sed 'H;1h;$!d;x;s/\n/ | /g' iplist

real    0m4.903s

アビナッシュラージ:

time python2.7 -c'
import sys
with open(sys.argv[1]) as f:
    print " | ".join(line.strip() for line in f)' iplist

real    0m3.434s

そして

値0x00ff:

while read -r ip; do printf '%s | ' "$ip"; done < iplist

real    3m4.321s

意味はです184.321s。驚くべきことに、これは次の200倍遅いです。マックサイフソリューションです。



awkを使用する他の方法は次のとおりです。

awk '$1=$1' RS= OFS=' | ' iplist

real    0m4.543s

awk '{printf "%s%s",sep,$0,sep=" | "} END {print ""}' iplist

real    0m5.511s

真珠:

perl -ple '$\=eof()?"\n":" | "' iplist

real    0m9.646s

パラメータ:

xargs <iplist printf ' | %s' | cut -c4-

real    0m6.326s

ヘッド+貼り付け+tr+catの組み合わせ:

{ head -n -1 | paste -d' |' - /dev/null /dev/null | tr \\n \ ; cat ; } <iplist

real    0m0.991s

IPリストがそれほど大きくない場合GNU coreutils(たとえば、最大50000個のIP)、次のコマンドを使用してこれを実行することもできますpr

pr -$(wc -l infile) -tJS' | ' -W1000000 infile >outfile

どこ

-$(wc -l infile)         # no. of columns (= with no. of lines in your file)
-t                       # omit page headers and trailers
-J                       # merge lines
-S' | '                  # separate columns by STRING
-W1000000                # set page width

たとえば、6行ファイルの場合:

134.28.128.0
111.245.28.0
109.245.24.0
128.27.88.0
122.245.48.0
103.44.204.0

注文する:

pr -$(wc -l <infile) -tJS' | ' -W1000 infile

出力:

134.28.128.0 | 111.245.28.0 | 109.245.24.0 | 128.27.88.0 | 122.245.48.0 | 103.44.204.0

答え3

あなたはそれを使用することができますアッ:

awk 'FNR!=1{print l}{l=$0};END{ORS="";print l}' ORS=' | ' file > new_file

ORS=' | '設定出力レコード区切り記号改行文字を置き換えます' | '

または、以下を使用して所定の位置に編集しますperl

perl -pe 's/\n/ | / unless eof' file

答え4

だから私はすべてについて間違っていました。そしてこの質問は私に多くのことを教えてくれましたpaste。 cuonglm が正しく指摘したように、pastein files in serial を使用しない限り-s、書き込み時に常に\ninfile リストの最後の ewline を出力に追加します。私はその動作が基本モードであると誤って信じていました。私は明らかに強化を楽しんだ誤解でしpaste -sた。busybox paste次のコマンドは広告どおりに機能しますbusybox

paste -d'|  ' - - infile </dev/null >outfile

しかし、仕様どおりに動作しません。正しい実装は、作成された各シーケンスに末尾の行をpaste追加し続けます。\nしかし結局、それは大きな問題ではありません。

paste -d\  - infile - </dev/null | paste -sd\| - >outfile

関連情報