パターン1に最も近い一致からパターン2より前のすべての行を印刷します。

パターン1に最も近い一致からパターン2より前のすべての行を印刷します。

この質問は以前に要求されたと確信していますが、正確なトリックを見つけることができません。

私の入力は次のとおりです。

Compiling File1
... commands ...

Compiling File2
... commands ...

Compiling File3
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find A

Compiling File4
... commands ...

Compiling File5
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find B

予想出力:

Compiling File3
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find A
---separator---
Compiling File5
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find B
---separator---

error:最も近い前の一致からCompiling現在の行、つまりエラーメッセージまで、各一致の全体的なコンテキストを印刷するシェルコマンドが必要です。正常にコンパイルされた他のすべてのファイルはスキップできます。

私は最後の一致が「コンパイル」されてから、すべてのテキストを含むパターンスペースを維持することで、awkまたはsedを使用してこれを簡単に達成できると思いますが、エラーなしで何千もの行がある可能性があります。非常に非効率的でしょうか?

答え1

関連して、keeping a pattern space comprising all text since the last match "Compiling", but there can be thousands of lines without an error. Would it be very inefficient?印刷を開始する前に、一致する区切り記号のペアを識別するために入力ファイルを2回通過するなど、他の選択肢よりも効率が悪く、入力がファイルに保存されているかどうかに関係なく動作するという利点がある。パイプ。

次の機能を備えたシステムを使用する場合、最も効率的なアプローチは、次の間に呼び出しで2を使用することですtacawktac

$ tac file |
    awk '/^error:/{f=1; print "---separator---"} f; /^Compiling/{f=0}' |
        tac
Compiling File3
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find A
---separator---
Compiling File5
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find B
---separator---

それ以外の場合は、すべてのUnixシステムのすべてのシェルでawkを使用してください。

$ awk '
    /^Compiling/ { buf="" }
    { buf = buf $0 "\n" }
    /^error:/ { print buf "---separator---" }
' file
Compiling File3
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find A
---separator---
Compiling File5
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find B
---separator---

または、複数文字のRSとRTにGNU awkを使用します。

$ awk -v RS='\nerror:[^\n]+' -v ORS='\n---separator---\n' '
    sub(/(^|.*\n)Compiling/,"Compiling") { print $0 RT }
' file
Compiling File3
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find A
---separator---
Compiling File5
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find B
---separator---

答え2

perl短絡モードがあるため、使用は非常に簡単です-00

perl -00 -ne 'print if /\nerror:/' file

出力:

Compiling File3
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find A

Compiling File5
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find B

追加されている場合は、| sed 's/^$/----separator----/'必要に応じて空白行の代わりに独自の区切り文字を追加することもできます。

答え3

Raku(以前のPerl_6)の使用

raku -e 'my @array; for slurp.split("\n\n") {@array.push($_)}; for @array {.put if /^Compiling .* \n error/};' 

入力例:

Compiling File1
... commands ...

Compiling File2
... commands ...

Compiling File3
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find A

Compiling File4
... commands ...

Compiling File5
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find B

出力例(1):

Compiling File3
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find A
Compiling File5
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find B

つまり、「Compiling...」部分は区切り文字から分離され、各要素は(「topic」変数を介して)プッシュさ\n\nれます。結果要素が...で始まり、最後の行から始まる...の場合にのみ印刷されます。@array$_@arrayCompilingerror

OPが行を要求した理由は明確ではありませんが---separator---(開始行と終了行の両方が明示的に指定されているため)、追加するのは簡単です。

raku -e 'my @array; for slurp.split("\n\n") {@array.push($_)}; for @array {put($_,"\n---separator---") if /^Compiling .* \n error/};'

出力例(2):

Compiling File3
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find A
---separator---
Compiling File5
... commands ...
In file included from ...
In file included from ...
In file included from ...
error: could not find B
---separator---

付録:メモリ効率が重要であるという意見でOPが述べられています。 Rakuではlinesルーチンが怠惰なので、これはおおよそのアプローチです(現在の各「コンパイル...エラー」ブロックは1行に返されます)。

raku -e 'for lines.split( "Compiling ") {say "ERROR Compiling "~$_ if m/error/};'

または

raku -e 'say "ERROR Compiling $_" if m/error/ for lines.split( "Compiling ");' 

出力例(3):

ERROR Compiling File3 ... commands ... In file included from ... In file included from ... In file included from ... error: could not find A  
ERROR Compiling File5 ... commands ... In file included from ... In file included from ... In file included from ... error: could not find B

https://speakerdeck.com/util/reading-files-cant-be-this-simple
https://raku.org

関連情報