複数行の正規表現(grep、sed、awk、perl)

複数行の正規表現(grep、sed、awk、perl)

複数行の正規表現が何十回も議論されていることはわかっていますが、私のパターンに合わせて機能することはできません。

説明しようと思います。私のディレクトリにいくつかのテキストファイルがあります。ファイルのテキストの例:

LINE OF TEXT 2
LINE OF TEXT 1
LINE OF TEXT 3

LINE OF TEXT 1
LINE OF TEXT 2
LINE OF TEXT 3

LINE OF TEXT 1
LINE OF TEXT 3

LINE OF TEXT 3
LINE OF TEXT 2
LINE OF TEXT 1

LINE OF TEXT 2
LINE OF TEXT 3

「LINE OF TEXT 1」(間に空白行はありません)に続く「LINE OF TEXT 2」の後に続く「LINE OF TEXT 3」を探してみたいです。

各行自体は正規表現でなければなりません(たとえば、「LINE」で始まり特定の数字で終わる行など)。

注:すべてのファイルに正しい行順序が含まれているわけではないため、パターンが一致するとパターンは印刷されず、ファイル名のみがSTDOUTに印刷されます。

1行正規表現でこれを実行できますか?たとえば、awk はファイルからパターンを検索し、パターンが見つかるとファイル名を STDOUT に出力します。その後、「find -exec」でこの正規表現を使用できます。

記載されているすべてのツール(grep、awk、sed、perl)が可能です。

ベストアンサー1

Awkを使用して、「Record Separator」変数を少なくとも2つの連続した改行文字に一致する正規表現に設定することでこれを行うことができます。

awk -v RS='\n\n+' '/1.*2.*3/' file.txt

フィールド区切り文字を単一の改行文字に設定することもできます。

awk -v RS='\n\n+' -F '\n' '$1 == "LINE OF TEXT 1" && $2 == "LINE OF TEXT 2" && $3 == "LINE OF TEXT 3"' file.txt

読みやすいように分類:

awk -v RS='\n\n+' -F '\n' '
  $1 == "LINE OF TEXT 1" &&
  $2 == "LINE OF TEXT 2" &&
  $3 == "LINE OF TEXT 3"
' file.txt

一致するものが見つかった場合にのみファイル名を印刷するには、次のようにします。

awk -v RS='\n\n+' -F '\n' '
  $1 == "LINE OF TEXT 1" &&
  $2 == "LINE OF TEXT 2" &&
  $3 == "LINE OF TEXT 3" {
    match++
  }
  END {
    if (match) {
      print FILENAME
    }
' file.txt

しかし、あなたが言うことを考えるとfindとともにawk、終了状態と印刷にはAwkを使用することをお勧めしますfind

find . -type f -exec awk -v RS='\n\n+' -F '\n' '
  $1 ~ /LINE OF TEXT 1/ &&
  $2 ~ /LINE OF TEXT 2/ &&
  $3 ~ /LINE OF TEXT 3/ {
    exit 0
  }
  END { exit 1 }
' {} \; -print

やりたいことがあればその他find印刷する前に、すでにこれを行う準備ができています(他の主要なジョブ)。

おすすめ記事