JoeSlav
JoeSlav

Reputation: 4795

How to obtain the first line after matched string regardless of string presence

Say I have this as input:

..pattern1...this
..pattern1...1
..pattern1...2
...

Or

..pattern1...0
..pattern2...0
..pattern1...1
..pattern2...1
..pattern2...2
..pattern1...this
...

I.e. list of lines containing only two types of patterns (strings). I'm trying to obtain the first line of pattern1 after the last line of pattern2. If there is no pattern2 then the first line of pattern1. Example output for both cases would be:

 ..pattern1...this

I can do either one of this cases separately with sed (like with this answer) but I wasn't able to get a command which would do both ad the same time.

Anyone can jump in and lend an hand? Thanks!

Upvotes: 2

Views: 966

Answers (2)

anishsane
anishsane

Reputation: 20980

awk '/pattern1/ && !line{line=$0} /pattern2/{line=""} END{print line}' file
  1. When pattern1 is found, set the line variable to entire line.
  2. When we find pattern1 again, ignore it. (since line will already be set.)
  3. When pattern2 is found, reset line variable, so that the next occurance of pattern1 is respected.

And Ed Morton's answer has already mentioned how to handle, if you want exact line match or if you want to take pattern from a shell variable. Adding my answer only to suggest that use of tac can be avoided.

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 203254

Given one interpretation of your question this might be what you need:

If pattern means regexp and you're OK with partial rather than full matches then:

tac file | awk '/pattern1/{line=$0; f=1} /pattern2/{exit} END{if (f) print line}'

If you need full regexp matches then add start/end anchors (/^pattern1$/) and compare to a specific field (e.g. $4 ~ /^pattern1$/) instead of the whole line if you need word instead of line matches.

If you need string matches instead of regexp then use index() or == against $0 or $N (where N is your target field number) as appropriate.

If pattern1 and pattern2 are shell variables and given a whole bunch of assumptions about what a "pattern" might be:

tac file | awk -v re1="$pattern1" -v re2="$pattern2" '$0 ~ re1{line=$0; f=1} $0 ~ re2{exit} END{if (f) print line}'

Upvotes: 1

Related Questions