大規模なコードディレクトリから文字列リストを効率的に取得する方法

大規模なコードディレクトリから文字列リストを効率的に取得する方法

文字列のリストがあり、各文字列ごとに大きなソースコードディレクトリに表示されることを確認したいと思います。

私が望むものを提供するGNU grepソリューションを見つけました。

for key in $(cat /tmp/listOfKeys.txt); do
    if [ "$(grep -rio -m 1 "$key" . | wc -l)" = "0" ]; then
        echo "$key has no occurence"; 
    fi
done

ただし、一致するものを早期に見つけても、常にディレクトリの下のすべてのファイルをgrepするため、非効率的です。検索する必要があるキーも多く、検索する必要があるファイルも多すぎるため、そのまま機能しません。

「標準」Unixツールを使用してこれを効率的に実行する方法を知っていますか?

ベストアンサー1

少なくとも、次のように単純化できます。

set -f # needed if you're using the split+glob operator and don't want the
       # glob part

for key in $(cat /tmp/listOfKeys.txt); do
   grep -riFqe "$key" . ||
    printf '%s\n' "$key has no occurrence"
done

これにより、最初の発生後に検索が停止され、キーが正規表現key(または可能なオプションgrep)と見なされなくなります。

ファイルを複数回読み取ることを防ぎ、キーのリストが1行に1つのキーであると仮定するには(上記のコードのように区切られたスペース/タブ/改行の代わりに)GNUツールを使用できます。

find . -type f -size +0 -printf '%p\0' | awk '
  ARGIND == 2 {ARGV[ARGC++] = $0; next}
  ARGIND == 4 {a[tolower($0)]; n++; next}
  {
    l = tolower($0)
    for (i in a) if (index(l, i)) {
      delete a[i]
      if (!--n) exit
    }
  }
  END {
    for (i in a) print i, "has no occurrence"
  }' RS='\0' - RS='\n' /tmp/listOfKeys.txt

keyaが表示されている場合は検索を停止し、すべてのキーが見つかったら停止し、ファイルを一度だけ読むように最適化されています。

キーがにあるとしますlistOfKeys.txt。キーは小文字で出力されます。

上記のGNUismは、NULで区切られたレコードを処理する機能-printf '%p\0'と同じです。最初の2つの問題は、次のように解決できます。ARGINDawk

find . -type f -size +0 -exec printf '%s\0' {} + | awk '
  step == 1 {ARGV[ARGC++] = $0; next}
  step == 2 {a[tolower($0)]; n++; next}
  {
    l = tolower($0)
    for (i in a) if (index(l, i)) {
      delete a[i]
      if (!--n) exit
    }
  }
  END {
    for (i in a) print i, "has no occurrence"
  }' step=1 RS='\0' - step=2 RS='\n' /tmp/listOfKeys.txt step=3

3番目の問題も同様のトリックを使用して解決できます。これしかし、おそらく努力する価値はないでしょう。バラより裸足IOソリューション問題を完全に迂回する方法を探しています。

おすすめ記事