次のテキストファイルがあります。
tom
and
jerry
went
to
america
and
england
各単語がどのくらいの頻度で表示されるかを知りたいです。
次のコマンドを試すと
cat test.txt |sort|uniq -c
私は次のような結果を得ます。
1 america
2 and
1 england
1 jerry
1 to
1 tom
1 went
しかし、部分一致も必要です。つまり、to
単語に現れる単語ですtom
。だから私の予想単語数to
は2です。unix
コマンドを使用できますか?
答え1
以下は方法ですが、非常にエレガントではありません。
$ sort -u file | while IFS= read -r word; do
printf '%s\t%s\n' "$word" "$(grep -cFe "$word" file)";
done
america 1
and 3
england 1
jerry 1
to 2
tom 1
went 1
答え2
離れてawk
いる:
awk '
!x {c[$0]; next}
{for (i in c) if (index($0, i)) c[i]++}
END{for (i in c) print c[i]"\t"i}' file x=1 file | sort -k1rn
あなたのコメントは何を提供しますか?
3 and
2 to
1 america
1 england
1 jerry
1 tom
1 went
我々は、入力を2段階で処理します。最初のステップでは、さまざまな単語のリストをc
ハッシュテーブルのキーとして記録します。
2 番目のパスでは、ファイルの各行に対してすべてのキーを繰り返し、そのc
行でキーが見つかるとその値を増やします。
ファイル内の他の単語のリストは最終的にメモリに保存されます。これが英語の単語であれば、英語には200,000個未満の他の単語があるため問題になりません。
答え3
システムがクラッシュすることはありませんが、入力を数回解析するため、実行に時間がかかることがあります。入力ファイル名が「in」であるとします。
sort -u < in | while read w
do
printf "%d\t%s\n" `grep -c "$w" in` "$w"
done
あなたの意見では、次のことができます。
1 america
3 and
1 england
1 jerry
2 to
1 tom
1 went
答え4
部分一致が行の先頭に固定されているかどうかは不明です。答えが「はい」と仮定するとどうなりますか?可能ここでスピードを上げる方法は、Ancientコマンドでバイナリ検索を使用することですlook
。もちろん、look
入力ファイルをソートする必要があります。まず、元のファイルの順序付きバージョンを作成します。
sort file > file.sorted
次に、元のファイルを繰り返しながら、ソートされたlook
ファイルについて一度に1つの単語を見つけます。
while read -r word; do
printf "%s %d\n" "$word" "$(look -b "$word" file.sorted | wc -l)";
done <file
一部のシステムでは、バイナリ検索を強制するために-b
フラグを渡す必要はありません。look
ソートされたファイルのディスクキャッシュは、作業速度をさらに向上させるのに役立ちます。