Skip to main content
added 34 characters in body
Source Link
Ed Morton
  • 35.9k
  • 6
  • 25
  • 60

Probably most efficient is just to use 2 calls to tac with awk in between if you're on a system that has tac:

$ tac file |  awk '/error^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--- 

Probably most efficient is just to use 2 calls to tac with awk if you're on a system that has tac:

$ 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--- 

Probably most efficient is just to use 2 calls to tac with awk in between if you're on a system that has tac:

$ 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--- 
added 35 characters in body
Source Link
Ed Morton
  • 35.9k
  • 6
  • 25
  • 60

Regarding 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? - no, it probably wouldn't any less efficient than any alternative approach such as doing 2 passes of the input file to identify the matching pairs of delimiters before starting printing and it'd have the advantage that it will work whether the input is stored in a file or coming from a pipe.

UsingProbably most efficient is just to use 2 calls to tac with awk if you're on a system that has tac:

$ 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--- 

Otherwise, just using any awk in any shell on every Unix box:

$ 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--- 

Alternatively, using GNU awk for multi-char RS and RT:

$ 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--- 

Regarding 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? - no, it wouldn't any less efficient than any alternative approach such as doing 2 passes of the input file to identify the matching pairs of delimiters before starting printing.

Using any awk in any shell on every Unix box:

$ 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--- 

Alternatively, using GNU awk for multi-char RS and RT:

$ 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--- 

Regarding 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? - it probably wouldn't any less efficient than any alternative approach such as doing 2 passes of the input file to identify the matching pairs of delimiters before starting printing and it'd have the advantage that it will work whether the input is stored in a file or coming from a pipe.

Probably most efficient is just to use 2 calls to tac with awk if you're on a system that has tac:

$ 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--- 

Otherwise, just using any awk in any shell on every Unix box:

$ 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--- 

Alternatively, using GNU awk for multi-char RS and RT:

$ 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--- 
added 35 characters in body
Source Link
Ed Morton
  • 35.9k
  • 6
  • 25
  • 60

Regarding 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? - no, it wouldn't any less efficient than any alternative approach such as doing 2 passes of the input file to identify the matching pairs of delimiters before starting printing.

Using any awk in any shell on every Unix booxbox:

$ awk -v'  ORS='---separator---\n' ' /^Compiling/ { buf="" }  {buf=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--- 

Alternatively, using GNU awk for multi-char RS and RT:

$ 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--- 

Using any awk in any shell on every Unix boox:

$ awk -v ORS='---separator---\n' '/^Compiling/{buf=""} {buf=buf $0 "\n"} /^error:/{print buf}' 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--- 

Alternatively, using GNU awk for multi-char RS and RT:

$ 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--- 

Regarding 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? - no, it wouldn't any less efficient than any alternative approach such as doing 2 passes of the input file to identify the matching pairs of delimiters before starting printing.

Using any awk in any shell on every Unix box:

$ 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--- 

Alternatively, using GNU awk for multi-char RS and RT:

$ 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--- 
Source Link
Ed Morton
  • 35.9k
  • 6
  • 25
  • 60
Loading