2017/01/30 修正

2017/01/30 修正

私はまだMac OSXターミナルを使用してコマンドラインツールを初めて使用しており、他の場所で答えを見逃していないことを願っていますが、数時間検索してきました。

3つの文字列の200の組み合わせを含むテキストファイル(strings.txtと呼ばれる)があります。 [2017/01/30 修正]最初の5行は次のとおりです。

"surveillance data" "surveillance technology" "cctv camera"
"social media" "surveillance techniques" "enforcement agencies"
"social control" "surveillance camera" "social security"
"surveillance data" "security guards" "social networking"
"surveillance mechanisms" "cctv surveillance" "contemporary surveillance"

行1などの監視データがバイグラム/ 2語句と一緒に保持されている限り、strings.txtを別の形式に変更できます。 (つまり、以下の@MichaelVehrsの答えのように、必要に応じて引用符を削除できます。)

800を超えるファイルを含むディレクトリで、少なくとも1つの文字列の組み合わせ(ファイル内の任意の場所)を含むファイルを検索しようとしています。私の初期のアイデアは、次のスキーマファイルでegrepを使用することでした。

egrep -i -l -r -f strings.txt file_directory

ただし、1行に1つの文字列がある場合にのみ機能させることができます。私が識別する必要があるファイルには、指定されたパターンの3つの文字列がすべて含まれているため、これは望ましくありません。 grepパターンファイルに一種のAND演算子を追加する方法はありますか?または、他の機能/ツールを使用して目的を達成するための別の方法はありますか?とても感謝しています!

2017/01/30 修正

以下の@MichaelVehrsの答えはとても役に立ちました。以下の内容を読むことができるように編集しました。

while read one two three four five six
do grep -ilFr "$one $two" *files* | xargs grep -ilFr "$three $four" |  xargs grep -ilFr "$five $six"
done < *patternfile* | sort -u

この答えは、スキーマファイルに引用符で囲まれていない文字列が含まれている場合に機能します。残念ながら、パターンファイルの最初の行にあるパターンとのみ一致するようです。理由を知っている人はいますか?

2017/01/29 修正

grep 複数値に関する同様の質問は次のとおりです。以前に質問しましたANDただし、他のファイルのパターンファイルstrings.txtにある3つの文字列の組み合わせのうちの1つを一致させるロジックが必要です。一致する操作を実行するには、strings.txtの形式を変更する必要があるかもしれないことを知っており、提案を受けたいと思います。

ベストアンサー1

私はperl次のようなものを使います:

perl -MFile::Find -MClone=clone -lne '
  # parse the strings.txt input, here looking for the sequences of
  # 0 or more characters (.*?) in between two " characters
  for (/"(.*?)"/g) {
    # @needle is an array of associative arrays whose keys
    # are the "strings" for each line.
    $needle[$n]{$_} = undef;
  }
  $n++;

  END{
    sub wanted {
      return unless -f; # only regular files
      my $needle_clone = clone(\@needle);
      if (open FILE, "<", $_) {
        LINE: while (<FILE>) {
          # read the file line by line
          for (my $i = 0; $i < $n; $i++) {
            for my $s (keys %{$needle_clone->[$i]}) {
              if (index($_, $s)>=0) {
                # if the string is found, we delete it from the associative
                # array.
                delete $needle_clone->[$i]{$s};
                unless (%{$needle_clone->[$i]}) {
                  # if the associative array is empty, that means we have
                  # found all the strings for that $i, that means we can
                  # stop processing, and the file matches
                  print $File::Find::name;
                  last LINE;
                }
              }
            }
          }
        }
        close FILE;
      }
    }
    find(\&wanted, ".")
  }' /path/to/strings.txt

これは、文字列検索の回数を最小限に抑えることを意味します。

ここではファイルを1行ずつ処理します。ファイルが非常に小さい場合、全体的に処理すると作業が少し簡単になり、パフォーマンスが向上する可能性があります。

リストファイルは次の場所にあると予想されます。

 "surveillance data" "surveillance technology" "cctv camera"
 "social media" "surveillance techniques" "enforcement agencies"
 "social control" "surveillance camera" "social security"
 "surveillance data" "security guards" "social networking"
 "surveillance mechanisms" "cctv surveillance" "contemporary surveillance"

形式に応じて、各行には引用符(二重引用符を含む)で囲まれた特定の数(必ずしも3である必要はありません)の文字列があります。引用符付き文字列自体には二重引用符文字を含めることはできません。二重引用符文字は、検索中のテキストの一部ではありません。つまり、リストファイルに次のものが含まれている場合:

"A" "B"
"1" "2" "3"

これは、現在のディレクトリと次のいずれかを含むその下のすべての一般ファイルへのパスを報告します。

  • A両方B
  • または(独占または) すべて123

どこでも。

おすすめ記事