これはおそらく一般的で簡単な作業ですが、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:
最初はa
0に設定されています。空白行(例)が見つかるたびに^$
値を確認し、a
条件付きで印刷してb
リセットしますa
。"foo"
行の先頭で前にコロンが表示されたら、これを1に設定しますa
。行の先頭でsrc:
()に会うと、それをに保存します。最後の場合はもう一度確認し、その場合は印刷します。^
b
a == 1
b
答え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}'