1

Good morning,

I am trying to write a UNIX script for a file with multiple duplicate patterns, followed by the pattern I am looking for. This question is very similar to:

"Get the last occurrence of a pattern before another pattern". However I do not have 'tac' (or 'tail -r'), and am looking to return the last occurrence of String1 before String2, and String2 also.

output.out:

...
Condition 1: A
foo
Condition 1: B
foo
Condition 2: C
foo
Condition 1: D
foo
Condition 1: E
foo
Condition 2: F
...

I'd like to write a grep / sed / awk script to return:

Condition 1: B
Condition 2: C
Condition 1: E
Condition 2: F

Since Condition 1 is always 'x' lines above Condition 2, I have tried using:

grep -B x "Condition 2"

And going from there, but for some reason the second occurrence in the resulting script output stops a few lines from the top (therefore not displaying Condition 1), due to blank lines in between Condition 1 / 2 maybe, I'm not sure the reason. So I've abandoned using grep -B. I think tac would help as I could grep 'backwards', but I don't have the tac command (or tail -r) on my environment.

Was wondering if anyone had any advice, would be much appreciated. Thanks for your time and help in advance.

peterh
  • 9,731
Henry
  • 109
  • Out of curiosity, why don't you have tac or sort -r? – DopeGhoti Dec 20 '16 at 21:00
  • We have 'sort -r' but it sorted the data based on the first column field. Not sure why we don't have an executable for tac, I figured it would be standard for UNIX applications. – Henry Dec 20 '16 at 21:10
  • What OS, distribution, version, etc.? – jayhendren Dec 20 '16 at 21:10
  • Using KornShell within MKS Toolkit 9.6, emulating UNIX on Windows 7. – Henry Dec 20 '16 at 21:18
  • Per my post there: sed '/Condition 1/h;/Condition 2/!d;x;/Condition 1/!d;G' file ... so instead of quitting like there just append hold space to pattern space G and there you have it... – don_crissti Dec 21 '16 at 13:42

2 Answers2

3

Well, if grep doesn't work correctly, it is uncertain whether awk does, but you could try this:

awk '/Condition 1/ { acc = $0; } /Condition 2/ { print acc; print; }' input
  • Looks like this does exactly what I was looking for, appreciate it very much. Even took out the legwork of removing the foo stuff. Awk always seems to come through, very reliable, when I have issues with grep and sed. Thank you very much sir. – Henry Dec 21 '16 at 14:52
  • This will print the Condition 1 line and Condition 2 line, but nothing in between them (no foo). Is there a simple modification to the command in this answer that includes printing everything between the last 'Condition 1' before 'Condition 2'? – Henry Nov 14 '17 at 21:41
1

A more generic use based on alternate condition (not always in cycle 2-1). It remember last condition and compare if it change or not and print last condition line if it change, if not remember it. Also print last remeber at exit and initiate the remeber cycle with first condition occuring.

awk -F '[[:blank:]:]*'
   /^Condition/ { 

      if (Index == $2) Last = $0
       else if (Index ~ /^$/) Index = $2; Last = $0
             elseprint Last
      Index = $2
      }
   END { print Last }
   ' YourFile