views:

808

answers:

2

Consider the input:

=sec1=
some-line
some-other-line

foo
bar=baz

=sec2=
c=baz

If I wish to process only =sec1= I can for example comment out the section by:

sed -e '/=sec1=/,/=[a-z]*=/s:^:#:' < input

... well, almost.

This will comment the lines including "=sec1=" and "=sec2=" lines, and the result will be something like:

#=sec1=
#some-line
#some-other-line
#
#foo
#bar=baz
#
#=sec2=
c=baz

My question, is what is the easiest way to exclude the start and end lines from a /START/,/END/ range in sed.

I know that for many cases refinement of the "s:::" claws can give solution in this specific case, but I am after the generic solution here.

In "Sed - An Introduction and Tutorial" at http://www.grymoire.com/Unix/Sed.html#uh-29 Bruce Barnett writes: "I will show you later how to restrict a command up to, but not including the line containing the specified pattern.", but I was not able to find where he actually show this.

The "USEFUL ONE-LINE SCRIPTS FOR SED" Compiled by Eric Pement has the at http-collon-slash-slash-sed-dot-sourceforge-dot-net-slash-sed1line-dot-txt [URL mangled due to "new users can only post a maximum of one hyperlink" limitation] I could find only the inclusive example:

# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p'             # case sensitive
+5  A: 

This should do the trick:

sed -e '/=sec1=/,/=sec2=/ { /=sec1=/b; /=sec2=/b; s/^/#/ }' < input

This matches between sec1 and sec2 inclusively and then just skips the first and last line with the b command. This leaves the desired lines between sec1 and sec2 (exclusive), and the s command adds the comment sign.

Unfortunately, you do need to repeat the regexps for matching the delimiters. As far as I know there's no better way to do this. At least you can keep the regexps clean, even though they're used twice.

This is adapted from the SED FAQ: How do I address all the lines between RE1 and RE2, excluding the lines themselves?

Ville Laurikari
Yes, this exactly what I was looking for.Thanks.
Chen Levy
A: 

you could also use awk

awk '/sec1/{f=1;print;next}f && !/sec2/{ $0="#"$0}/sec2/{f=0}1' file
ghostdog74