web-dev-qa-db-ja.com

grepを使用してディレクトリのすべてのファイル内のすべての単語の出現を数える方法は?ただし、カウントはファイルごとに単語ごとに1回だけ増分されます

私はすでに同様の質問をしましたが、人々は私が尋ねていることを誤解しました。私は、ファイルごとに単語ごとに1回だけ単語数を増やして、すべての単語のリストを生成する方法を尋ねていました。

たとえば、10個のファイルがあるディレクトリがあります。bashコマンドを使用して、出現するファイルの数に応じて1〜10の値を示す単語のリストを生成します。

10 The
10 and
8 bash
7 command
6 help....

等.

grep -l Word *| wc -lが単一の単語を検索することはすでに知っていますが、すべての単語のリストを作成したいと思います。

これをtr '[A-Z]' '[a-z]' | tr -d '[:punct:]'と組み合わせて、大文字の単語が重複せず、句読点が削除されるようにする方法はありますか?

5
Cnvrsn

ここではPerlを使用します:

Perl -T -lne '
  for (/\w+/g) {$count{lc $_}->{$ARGV}=undef}
  END {print "$_: " . keys %{$count{$_}} for keys %count}' ./*

これは、ハッシュのハッシュを構成します$count{Word}は、Wordが見つかったファイルの名前がキーであるハッシュへの参照です(そして、ここではundef)。

最後に、これらのハッシュごとに(つまり、見つかった単語ごとに)要素の数(つまりファイルの数)を数えるだけです。

2

関連のないものを検索しているときに、元の answer here by @Mehmetを見つけたところ、機能しますが、非常に非効率で、すべての一意のWordごとに各ファイルを再度読み取る必要がありますファイル! @Jeffの2番目の回答は、cat file |罪の影響と説明の中で最悪の場合でも、かなり複雑です。

必要なのはすべてのデータのシングルパスだけであり、以前の回答を効果的に組み合わせることで定式化できます。

find . -maxdepth 1 -type f -print |
while read file; do
    egrep -h -o "[[:alnum:]][[:alnum:]_-]*" "$file" |
    tr '[A-Z]' '[a-z]' |
    sed "s|^|$file\||"
done |
sort -t '|' -k 2 |
uniq |
awk -F '|' '{
    if (lw != $2) {
        print fc " " lw;
        fc = 0;
    }
    lw = $2;
    fc++;
}'

ファイル名にパスが含まれている場合やスペースが含まれている場合は、フィールドセパレータの選択が重要であることに注意してください。 egrepによって印刷されるWordの一部であってはならず、ファイル名やディレクトリ名に表示される可能性が低いため、|文字を選択しました。

1
Greg A. Woods