[NCLUG] sed help ?

Tkil tkil at scrye.com
Fri Feb 28 19:02:18 MST 2003


>>>>> "Gabriel" == Gabriel L Somlo <somlo at acns.colostate.edu> writes:

Gabriel> Do you guys know how I could delete the line containing 'some
Gabriel> pattern' *and the line immediately following it* (regardless
Gabriel> of content) ?

Gabriel> 	cat foo | sed -e '/some pattern/d'  > bar

Unnecessary use of "cat", btw: 

  sed -e '...' < input.txt > output.txt

I think that even the input redirection might be unnecessary:

  sed -e '...' input.txt > output.txt

>>>>> "Matt" == Matt Jibson <dolmant at engr.colostate.edu> writes:

Matt> Why not use egrep -v and search for something like 'some
Matt> pattern\n[^\n]*\n'?

And, of course, there's Perl:

  perl -lnwe 'if    ($skip) { $skip = 0 }
              elsif (/.../) { $skip = 1 }
              else          { print }'

Hm... looking at my perl above, I could abuse it into:

  perl -lnwe '( $skip || /.../ ) && ( $skip = !$skip, 1 ) || print'

Testing... interesting: how do you want to handle the case where the
next line (after a match) *also* matches -- would you delete the first
non-matching line after all contiguous matches, or would you just
delete it and ignore content?  Given the list

  one
  two
  three
  four
  five
  six

And the pattern /^t/, would you print 'four' or not?

Both of the above do print it:

| $ cat in.txt
| one
| two
| three
| four
| five
| six
| $ perl -lnwe 'if    ($skip) { $skip = 0 }
| >             elsif (/^t/)  { $skip = 1 }
| >             else          { print }' in.txt
| one
| four
| five
| six
| $ perl -lnwe '( $skip || /^t/ ) && ( $skip = !$skip, 1 ) || print' in.txt
| one
| four
| five
| six

The first one can be modified to ignore first line after whole string
of matches by rearranging the first two clauses:

| $ perl -lnwe 'if    (/^t/)  { $skip = 1 }
| >             elsif ($skip) { $skip = 0 }
| >             else          { print }' in.txt
| one
| five
| six

Modifying the second is hairier, due to my cleverness with the toggle.

Thinking outside the write-it-yourself box, there is also a "context
grep" utility, which might be bendable to this task.  Hmm... gnu grep
has this:

  `-A NUM'
  `--after-context=NUM'
       Print NUM lines of trailing context after matching lines.

Which means that we might be able to get away with something like
this:

  grep -v -A 1 -B 0 '...'

But I couldn't make it do what I wanted it to do.  Alas.

t.



More information about the NCLUG mailing list