Skip to main content
6 of 6
added 23 characters in body
αғsнιη
  • 41.9k
  • 17
  • 75
  • 118
awk '/^ABC/ && pre { print dpre ORS $0; pre=""; next } { if(pre) print pre; pre=dpre=$0; sub(/ {0,4}/, "END ", dpre) } END{ if(pre) print dpre }' infile 

first block will be executed only if a line starts with ABC string and when a temporary variable pre also was set otherwise next block will be executed.

the END{...} block will be executed only once and after end of all.

for the first line of course still pre variable doesn't set yet, so second block will be executed and it does following:

  • if there was things inside pre print it first if(pre) print pre (with this we delay printing of previous line in order to check if next line starts with ABC or not, because we need to add END in front of that line)

  • then we copy that line into say two separate variables pre and dpre (one would be untouched (later we need print it untouched) and for the another one in sub(/ {0,3}/,"END ", dpre) we are prepending the END string into dpre.

    Note that with {0,4} (zero or maximum 4 spaces; 4 is obtained from the length of END<SPC>) we ensure that the END string will be always prepended as well as preventing truncating the original line value if there was no spaces at all.


Below you can trace each iteration of the command for your own understanding:

  • REPEAT
  • Read a line; Is it start with ABC (/^ABC/)?
    • no; then do nothing and next block will be executed; go to 2nd-Block
    • yes; Is pre was set?
      • yes, then do these
        • print content of the dpre variable then a single newline ORS and then current line itself
        • empty variable pre="" and jump to REPEAT because of next statement tell that.
      • no; then do nothing and next block will be executed; go to 2nd-Block
  • 2nd-Block
    • is pre was set?
      • yes; do these
        • print pre it's set in "if(pre) print pre";
        • update current line into both variables pre=dpre=$0;
        • prepend END string for dpre.
      • no; do these
        • update current line into both variables pre=dpre=$0;
        • prepend END string for dpre.
  • if END of file; print last state of the dpre variable if it was set, else jump to REPEAT.
  • finish
αғsнιη
  • 41.9k
  • 17
  • 75
  • 118