出力に他の式が含まれている場合は、式に一致する行をstdoutとして印刷します。

出力に他の式が含まれている場合は、式に一致する行をstdoutとして印刷します。

これはおそらく一般的で簡単な作業ですが、Webの例やawk/sed/grepのマニュアルでは理解できません。

したがって、シナリオは次のようになります。

  • 入力ファイルの各行に対して複数行の結果を印刷する内部コマンドラインツールがあります。
  • 500K行の入力ファイルがあります。
  • ツールの出力には常に "src:/some/directory" と同様の行があります。
  • 同じ出力に特定の文字列「foo」がある場合にのみ、この行を抽出したいと思います。

行数はこれらの間で異なる可能性があるため、この質問は多少関連していますが、正確に私が望むものではありません。 awkを使用して単一のファイルで複数の正規表現を一致させる

awk、sed、または grep を使ってこれを行うにはどうすればよいですか? Pythonを使ってこれを行うことはできますが、awk / sedを学びたいのですが、これは良い例かもしれないので、そうしたくありません。

これが私がgrepで試したことです。

tool -inputfile | if grep "foo"; then grep "src: " ; fi > result.txt

バッファリング関連の理由により、予想される結果は出ません。

awkを試してください:

tool -inputfile | awk '{for (i=1;i<NF;i++) {if(match($i, "foo")) print ??? }}' > result.txt

このスクリプトに「src:」を含む行をどのように印刷できますか?

このツールの出力例:

出力1:

src: /usr/bin 
param1: value1 value2 
param2: "foo" 
param3: "bar" "spam" 
param4: "eggs" "spam" "spam"

出力2:

src: /dev/null
param1: value1 value2
param2: "ham" "spam" "eggs"

そのため、どちらの場合も最初のケースであるsrc:/ usr / binだけを抽出しようとしました。

答え1

src:行の先頭に表示され、foo引用符で囲まれていて、前にスペースがあり、行の前にコロンが必要であることがわかっている場合は、次のようにします。

awk 'BEGIN{a=0} /^$/{if(a==1) print b; a=0} /:.* "foo"/{a=1} /^src:/{b=$0} END{if(a==1) print b}'

aパターンがfoo入力ブロックに表示されるかどうかを記憶するために変数を使用し、行を保存bするために変数を使用します。src:最初はa0に設定されています。空白行(例)が見つかるたびに^$値を確認し、a条件付きで印刷してbリセットしますa"foo"行の先頭で前にコロンが表示されたら、これを1に設定しますa。行の先頭でsrc:()に会うと、それをに保存します。最後の場合はもう一度確認し、その場合は印刷します。^ba == 1b

答え2

シンプルなawk

awk '/src/{a=$0}/foo/{b=1}b&&a{print a;exit}'

他の形式や他の方法で他の場所で見つけることができるsrc場合foo

awk '/^src/{a=$0}/"foo"/{b=1}b&&a{print a;exit}'

fooがいつも後ろに来たらsrc

awk '/^src/{a=$0}/"foo"/{print a;exit}'

ファイルに複数のsrcブロックがあり、fooを含む各ブロックを印刷したい場合

awk '/^src/{a=$0;b=0}/"foo"/{b=1}b&&a{print a;a=0}'

関連情報