Re: Print ranges without its BEGIN and END patterns

"Tim Chase [email protected] [sed-users]" <[email protected]>
Newsgroups gmane.editors.sed.user
Message-ID <[email protected]>
On 2015-03-05 14:21, 'Seeger, Stephan'
> I'm really new to using sed. While experimenting in order to print
> ranges without its BEGIN and END patterns I accidentially came
> across that given a string variable:

New to sed and you stumble upon this awesome hack?!  Nicely done!  I
don't think I've ever seen this one before

> sed -n '/second/,/fourth/{//!p}'
[snip]
> Unfortunately I didn't find this described anywhere in manuals nor
> the internet. Probably there's anyone out there who  can explain
> whether this is a bug or a feature...and how/why it works.

As best I can tell, this is working as a side-effect of documented
behavior.  The general process/flow would be something like

 1) check if this line matches the start-of-range pattern
 ("second"). As a side-effect of this, the "last pattern" gets set to
 the same thing and we internally annotate that we're inside this
 range.

 2) it matches, so do the stuff inside the "{...}"

 3) Check to see if the current line matches the "last
 pattern" ("//"). It does, so we don't ("!") execute the print command

 4) proceed to the next line

 5) we're inside the range, so we check for the end-of-range pattern.
 As a side-effect, the "last pattern" gets set.  It doesn't match, so
 we continue to execute the "{...}"

 6) we check if "third" matches the "last pattern" (now the
 end-of-range pattern). It doesn't, so we print it

 7) we're inside the range, so we check for the end of the range.
 As a side-effect, the "last pattern" gets set.  It does match, so
 we continue to execute the "{...}", and then unset the internal
 "within this range" flag

 8) executing the "{...}", we check if "fourth" matches the "last
 pattern".  It does, so we don't print it.

 9) we're now outside the range, so we resume looking for "second"
 and 

It doesn't even break if the start-pattern appears within the range:

 $ printf '%s\n' a b c d e d f g h i j | sed -n '/d/,/g/{//!p}'
 e
 d
 f

(note that "d" does come between the opening "d" and the closing "g",
so it gets printed)

So I'd claim that this is some of the most elegant sed hackery I've
seen in a while (at least for such a short piece of code).

-tim
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.