패턴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를 사용하는 것입니다 tac.awktac

$ 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루틴이 게으르기 때문에 이는 대략적인 접근 방식입니다(현재 각 "컴파일...오류" 블록은 한 줄에 반환됩니다).

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

관련 정보