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
preprint it firstif(pre) print pre(with this we delay printing of previous line in order to check if next line starts withABCor not, because we need to addENDin front of that line)then we copy that line into say two separate variables
preanddpre(one would be untouched (later we need print it untouched) and for the another one insub(/ {0,3}/,"END ", dpre)we are prepending theENDstring intodpre.Note that with
{0,4}(zero or maximum 4 spaces; 4 is obtained from the length ofEND<SPC>) we ensure that theENDstring 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
prewas set?- yes, then do these
- print content of the
dprevariable then a single newlineORSand then current line itself - empty variable
pre=""and jump to REPEAT because ofnextstatement tell that.
- print content of the
- no; then do nothing and next block will be executed; go to 2nd-Block
- yes, then do these
- 2nd-Block
- is
prewas set?- yes; do these
- print
preit's set in "if(pre) print pre"; - update current line into both variables
pre=dpre=$0; - prepend
ENDstring fordpre.
- print
- no; do these
- update current line into both variables
pre=dpre=$0; - prepend
ENDstring fordpre.
- update current line into both variables
- yes; do these
- is
- if END of file; print last state of the
dprevariable if it was set, else jump to REPEAT. - finish