部分一致を使用してファイルから単語の頻度を取得します。

部分一致を使用してファイルから単語の頻度を取得します。

次のテキストファイルがあります。

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ソートされたファイルのディスクキャッシュは、作業速度をさらに向上させるのに役立ちます。

関連情報