ファイル内の一意の単語とその数を取得したいと思います。次のコマンドを実行すると、
sort words.txt | uniq -c
2 america
4 and
1 england
1 file
1 for
1 place
しかし、次の形式で出力したいです。
america,2
and,4
england,1
file,1
for,1
place,1
私の入力ファイルは約30〜40 Gbです。それでは、この形式で出力を印刷する最良の方法は何ですか?
答え1
awk
コマンドの最後に行を追加できます。例えば、
sort words.txt | uniq -c | awk '{print $2","$1}'
デフォルトでは、最初の列の前に2番目の列をカンマで区切って配置します。 30-40Gbファイルでこれを実行するのにどれくらいの費用がかかっているのかわかりません。
答え2
awk自体を使用してこれを行うことができます...
以下で試してください。
awk '{j[$0]++} END {for (i in j) print i","j[i]}' words.txt
答え3
そしてsed
:
sort words.txt | uniq -c | sed -E 's/^ *([0-9]) (.+)/\2,\1/g'
GNU、Busybox、BSDの実装でテストされていますsed
。出力は次のとおりです。
america,2
and,4
england,1
file,1
for,1
place,1
200MBファイルでテストした結果、それsed
自体はまだかなり高速であることがわかりました。
$ time sed -E 's/^ *([0-9]) (.+)/\2,\1/g' HUGE | head
america,2
and,4
england,1
file,1
for,1
place,1
america,2
and,4
england,1
file,1
real 0m0.006s
user 0m0.003s
sys 0m0.006s
-i
ただし、これら2つのオプションを使用して>
シェル演算子を使用して出力をリダイレクトすると、データをディスク上のファイルに保存するのに時間がかかります。
$ time sed -i -E 's/^ *([0-9]) (.+)/\2,\1/g' HUGE
real 0m45.793s
user 0m31.965s
sys 0m13.574s
$ time sed -E 's/^ *([0-9]) (.+)/\2,\1/g' HUGE > HUGE_NO_I
real 0m29.016s
user 0m28.684s
sys 0m0.119s