6
votes

I have a text file that looks like this:

-+- beginning text
hey there
hi there
ho there
-+- ending text
other stuff
that is
immaterial for
my purposes

I want to only grab the lines between the -+- patterns, so it will return:

hey there
hi there
ho there

The standard awk way:

awk '/beginning text/ {flag=1;next} /ending text/ {flag=0} flag {print}'

Works great as long as "beginning text" and "ending text" are different patterns.

Alas, for what I need, "Beginning text" and "Ending text" can change. The only consistent part of the two lines are the "-+-". All the rest of the text in the file can be completely different; I can't rely on any consistent patterns. The only reliable text is the -+-. And the awk fails when the two strings are identical.

Any ideas for how I can returns the lines between two discrete instances of the same pattern exclusive of the lines containing the patterns? Doesn't have to be awk, just something that will work in a bash shell script.

4

4 Answers

9
votes

If the pattern is the same and you don't want the pattern lines printed out then just combine the two patterns by inverting the flag each time you see the pattern.

awk '/^-\+-/ {flag=!flag; next} flag {print}'
3
votes
cat ttt
aaaa
bbbb
ccccc
bbbb
xxxxx
gggg
awk '/bbb/ {flag=1-flag; next} {if (flag) {print $0}}' ttt
ccccc
3
votes

Using sed:

sed -n '/^-+-/,/^-+-/ { /^-+-/! p; }'

Using awk:

awk '/^-\+-/ { flag++; next } flag % 2'

Using perl:

perl -ne 'if (/^-\+-/) { $a ^= 1; next } print if $a'

Using new(ish) perl:

perl -ne 'print if /^-\+-/.../^-\+-/ and !/^-\+-/'

Using bash:

#! /bin/bash
while IFS= read -r line; do
    if [[ $line =~ ^-\+- ]]; then
        let flag^=1
        continue
    fi
    if [ $flag -ne 0 ]; then
        printf '%s\n' "$line"
    fi
done

Output:

hey there
hi there
ho there
2
votes

For a generic use (same or different pattern for start/stop)

awk '#     Start pattern
     $0 ~ /^-\+-/ {flag=1;next}
     #     Stop   pattern
     $0 ~ /^-\+-/ {flag=0;next}

     flag { print}
    ' YourFile

note: + need to be escaped in regex for litteral use

Adapted based on remark of @fedorqui