Donald Hall
Donald Hall

Reputation: 1

Match a line, run an if statement, bash scripting

I am not really sure if this is already out there but I am having some trouble trying to express what I want to be done in a search field.

Say I had a file like the following

foo1
foo2
foo3
barbarbar
barbarbar
barbarbar
foo4
foo5
barbarbar
barbarbar
barbarbar
foo6
foo7

I want to only get the fields that have something other than "foo#" after a "foo#". I also want the "foo#" to be printed if it does have barbarbar after it and everthing that until the next "foo#". An example output would be below.

foo3
barbarbar
barbarbar
barbarbar

foo5
barbarbar
barbarbar
barbarbar

Upvotes: 0

Views: 44

Answers (2)

glenn jackman
glenn jackman

Reputation: 246774

I don't normally like to post answers to questions that "haven't tried", but I've got some time on my hands. I like to use awk for stuff like this:

The "state machine" approach:

awk '
    /foo/ && afterfoo != "" { print currentfoo; print afterfoo; afterfoo = "" }
    /foo/  { currentfoo = $0 }
    !/foo/ { afterfoo = afterfoo $0 "\n" }
    END    { if (afterfoo != "") {print currentfoo; print afterfoo} }
' file

The "reverse-process-reverse" approach:

tac file | awk '
    !/foo/ { print; seenfoo = 0 }
    /foo/ && !seenfoo++
' | tac

Upvotes: 1

Aaron
Aaron

Reputation: 24802

It looks like this sed command will work :

sed -n '/^foo[0-9]$/{N;:l;/\nfoo[0-9]$/{D;bl};p;b};p'

I honestly regret trying to do that with sed though, the result is hardly comprehensible.

/^foo[0-9]$/{     # if a line matches fooX
    N                # retrieve another line
    :l               # we'll jump to here later ; label l
    /\nfoo[0-9]$/{   # if the following line matches fooX too
        D                # discard the first line and consume another one
        bl               # jump back to l
    }                # at this point we have a fooX line followed by a non-fooX line
    p                # print what we've matched
    b                # stop processing this line (jump to the end of the script)
}                 # reached when the first line read doesn't match fooX
p                 # print the line

Edit : now that I've laid it out this way, I notice that the p;b part can be removed since it will behave the same by reaching the last p. If I was the poor soul having to maintain this, I think I'd rather have it there though.

Upvotes: 2

Related Questions