kdubs
kdubs

Reputation: 1722

sed n doesn't seem to work quite the way I thought it would

I was trying to copy an example I found here : http://www.grymoire.com/Unix/Sed.html#uh-35a

here is the sed pattern

/^begin$/,/^end$/{
    /begin/n
    /end/!d
}

here's the first file

begin
one
end
last line

and here's the second

begin
end
last line

when I run the sed on the first file it deletes what's between the begin/end and all is well. When I run it on the second, it appears to miss the "end" and deletes the rest of the file.

running on first file

$ sed -f x.sed a
begin
end
last line

running on second

$ sed -f x.sed b
begin
end

notice how "last line" is missing on the second run.

I thought that "n" would print the current pattern and suck in the next one. It would then hit the /end/ command and process that.

as it is, it seems like it's somehow causing the end of the range to be missed. Will somebody explain what is happening?

Upvotes: 3

Views: 110

Answers (3)

user4401178
user4401178

Reputation:

I think you were close to getting it to do what you wanted. When you want to delete the next line after a match you simply need to pull it in with the sed n and then hit it with a delete d.

It looks like you want to skip the line after the line that starts with begin unless it's end and print all the other lines.

If so, the following should suffice:

/^begin$/,/^end$/{
/begin/{n;/end/!d}
}

It works by skipping the next line after begin except if it starts with end (/end/!).

Also see: sed or awk: delete n lines following a pattern

Upvotes: 0

kdubs
kdubs

Reputation: 1722

found another way around after @hek2mgl 's help. I can add a branch around the 2nd statement. I actually need this because I want to see the begin label. so you can also do this:

/^begin$/,/^end$/{
/begin/{ b skip }
/end/!d
:skip

}

Upvotes: 0

hek2mgl
hek2mgl

Reputation: 158120

It should be:

/^begin$/,/^end$/{
    /^begin$\|^end$/!d
}

Why was your command wrong?

The n command was wrong there. In the second example it will:

  1. begin ---> n read next line(important: this does not affect the state of the range address (begin,end))

    1a. end ---> /end/! does not apply. Don't delete the line

  2. last line ---> /end/! applies. Delete the line. (sed is still searching for a line that contains end because the n command skipped that line)

Upvotes: 1

Related Questions