user1777907
user1777907

Reputation: 1375

Bash: Find a string before another string in a file

I am trying to find the preceding string before another string. For example:

StringA <stuff 1>
StringA <stuff 2>
StringD
...
StringB <stuff 3>
StringA <stuff 4>
StringA <stuff 5>
StringA <stuff 6>
StringD
StringB <stuff 7>

I want to find all the "StringA" that JUST preceeds StringB in the file.

The output in this example would be:

StringA <stuff 2>
StringA <stuff 6>

I am able to do find the line numbers of all the StringB by using: grep -n "StringB"

Then I can use sed -n 1,$line_numberp which makes me go from line 1 to the line of StringB. I do grep "StringA" | tail -n1

This seems to be work but is a bit cumbersome. Is there any better way to achieve the desired result please?

Upvotes: 1

Views: 1534

Answers (4)

potong
potong

Reputation: 58473

This might work for you (GNU sed):

sed ':a;$!N;/^StringA/!D;/^\(StringA\).*\n\1/D;/.*StringB/!ba;P;D' file

This removes duplicate StringA lines retaining the last and when encountering a StringB line prints out the first string in the pattern space.

Upvotes: 0

MatthieuBizien
MatthieuBizien

Reputation: 1725

With awk :

awk '/^StringB/ { if(lastline ~ /^StringA/) {print lastline }} {lastline=$0}' $file

StringA and StringB can be regular expressions.

Upvotes: 1

Alex
Alex

Reputation: 11090

grep "\(StringA\|StringB\)" $file_name | grep -B 1 StringB | grep StringA

Upvotes: 3

perreal
perreal

Reputation: 98068

sed '/String[AB]/!d' input | 
   sed -n -e '/StringA/{:l /StringA/h;n;/StringB/{x;p;b};bl}'

With comments:

sed '/String[AB]/!d' input |      # remove lines not containing StringA/B
   sed -n -e '/StringA/{          # if line contains StringA, then
      :l                          # loop until StringB
          /StringA/h;             # keep the most recent A in the hold space
          n;                      # read a newline (overwrite pattern space)
          /StringB/!bl;           # loop up...
          x;p;b                   # get the most recent A, and print
   }'

Upvotes: 1

Related Questions