0

How can I display file content from some multi-line pattern to the end including the pattern itself?

I asked a similar question just now but it's different and I thought I should post this as a separate, new question. So please don't mark this duplicate simply because of that!

For example, if I had a text file like this:

cat
dog
fox
cow
dove
bird
bunny
gnu
hen
dove
bird
buffalo

and if my pattern was this:

dove
bird
bunny

what I'd like to get would be:

dove
bird
bunny
gnu
hen
dove
bird
buffalo

My real file is huge so if there are multiple ways to achieve this, I'd prefer faster ways.

  • 1
    What if the pattern appears multiple times in the file? – Thor Jun 21 '17 at 19:33
  • @Thor, in my particular situation, the pattern can't appear multiple times so it doesn't matter. – stacko Jun 21 '17 at 22:50
  • sed -e '1N;N;/dove\nbird\nbunny/!D' -e ':a' -e 'n;ba' will hold 3 lines at any time in the pattern space till the time the golden lines are found. At which point we setup a loop and keep spitting the pattern space till we hit the eof. – user218374 Jun 24 '17 at 4:51
0

If you want to print from the first time the pattern appears, it is easy. Follow the same logic I described in the other answer, but with some extra logic:

parse.sed

/^dove$/ {            # Match multi-line pattern
  N                   #  /
  N                   # /
  /\nbird\nbunny$/bb  # When matched jump to label b
}
d                     # Restart with next line if no match
:b                    # \
n                     #  Print the rest of the file
bb                    # /

Run it like this:

sed -f parse.sed infile

Or as a portable one-liner:

sed -n -e '/^dove$/{N;N;/\nbird\nbunny$/bb' -e '};d;:b' -e 'p;n;bb' infile

The output in both cases:

dove
bird
bunny
gnu
hen
dove
bird
buffalo
| improve this answer | |
0

Here's a Perl solution:

perl -0777 -ne 'print $1,$2 if m/(dove.bird.bunny)(.*)/sm' myfile

This outputs:

dove
bird
bunny
gnu
hen
dove
bird
buffalo

The -0777 switch turns on slurp mode which reads the whole file into memory. the use of sm modifiers to the match allows a dot to match a newline while treating the string as multiple lines.

The -n switch creates a read loop for the input file. When the sequence dove.bind.bunny is seen, it's captured in $1 with the remaining lines in $2 and this is what's printed if the overall match succeeds.

| improve this answer | |
0

awk solution:

awk -v RS=" " '{                        # considering space as record separator
                  for(i=1;i<=NF;i++) {  # iterating through all fields
                     if ($i=="dove" && $(i+1)=="bird" && $(i+2)=="bunny") { f=1 } 
                     if (f) print $i 
                  } 
               }' file

The output:

dove
bird
bunny
gnu
hen
dove
bird
buffalo
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.