Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

excluding first and last lines from sed /START/,/END/

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" 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.

In the "USEFUL ONE-LINE SCRIPTS FOR SED" Compiled by Eric Pement, I could find only the inclusive example:

# print section of file between two regular expressions (inclusive) sed -n '/Iowa/,/Montana/p'             # case sensitive 
like image 893
Chen Levy Avatar asked Jul 27 '09 09:07

Chen Levy


People also ask

How do you remove the first and last line in Unix?

1d deletes the first line ( 1 to only act on the first line, d to delete it) $d deletes the last line ( $ to only act on the last line, d to delete it)

How do I remove the first and last line in bash?

sed -i '$ d' filename . The -i flag edits file in place. This deletes the last line. To delete the first line, use sed -i '1,1d' filename .

How do you exclude the first line in Unix?

The first line of a file can be skipped by using various Linux commands. As shown in this tutorial, there are different ways to skip the first line of a file by using the `awk` command. Noteably, the NR variable of the `awk` command can be used to skip the first line of any file.

How do you specify the end of a line in sed?

Using `sed` to replace \n with a comma By default, every line ends with \n when creating a file. The `sed` command can easily split on \n and replace the newline with any character. Another delimiter can be used in place of \n, but only when GNU sed is used.


2 Answers

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?

like image 153
Ville Laurikari Avatar answered Oct 02 '22 07:10

Ville Laurikari


If you're not interested in lines outside of the range, but just want the non-inclusive variant of the Iowa/Montana example from the question (which is what brought me here), you can write the "except for the first and last matching lines" clause easily enough with a second sed:

sed -n '/PATTERN1/,/PATTERN2/p' < input | sed '1d;$d'

Personally, I find this slightly clearer (albeit slower on large files) than the equivalent

sed -n '1,/PATTERN1/d;/PATTERN2/q;p' < input

like image 25
Paul Whittaker Avatar answered Oct 02 '22 08:10

Paul Whittaker