Is sed buggy when pattern is newline for a delete command?

0

My goal is to print the content of a file up to (and excluding) a specific pattern and I'm using the following which works as expected (even when pattern is ^$):

sed -n '/pattern/!p;//q' file

In my quest to shorten the above command (you know, save a few bytes), I found that I could "invert" the negated print command and instead use a delete as follows:

sed '/pattern/d;//q' file  

which again works as expected except when /pattern/ refers to an empty line as in /^$/ and in that case it adds the empty line itself to the output, which is weird.

The file obviously contains an empty line in my case, which is where I want to split the content.

Any idea why this happens? Is sed buggy for this edge case? (the additional //q does quit immediately to save on processing time when using large files)

sed --version returns sed (GNU sed) 4.5

Paolo

Posted 2018-12-23T11:58:42.437

Reputation: 25

1d starts a new cycle so I'm surprised this q ever works for you. – Kamil Maciorowski – 2018-12-24T12:11:37.587

Answers

0

After further research, there is no winning solution:

sed '/^$/,$d' file

this is the best that I could find in terms of compactness, with the only drawback that it will process the whole file, which in some case might be undesirable (for instance, a large one)

sed '/^$/,$d;//q' file

adding the typical quit command doesn't help because the earlier range already encompasses the entire file

sed '/^$/q' file
sed '/^$/Q' file

these suggestions, although very compact, are not ideal (because of extra output / portability)

sed -n '/^$/q;p' file

this other suggestion is one that I had also found on my own in the meantime and it's somewhat fine given that it will quit as soon as the pattern is found, although I had hoped to get rid of the -n option which is where I started with all this...

Paolo

Posted 2018-12-23T11:58:42.437

Reputation: 25

3

With GNU sed you can run

sed '/pattern/Q' file

The q command prints the pattern space before quiting, Q command quits silently.

I think the negated command !p avoids q to print the pattern space.

sed -n '/pattern/!p;//q' file  

The -n option avoids q to print the pattern space. The other lines get printed because the address gets negated, so the p command is applied to all lines but those that contain /pattern/. Another way to write this would be

sed -n '/pattern/q;p' file

When match pattern, quit (without print due to the -n option). All other lines, print.

In this other script, d command deletes all pattern space and goes directly to the start of the sed script with a new line from input loaded.

sed '/pattern/d;//q' file  

edit- In this case I think //q will never be reached when there is a match.

echo -e 'one\ntwo\nthree\n\nfour\n\n'|sed '/^$/d;//q'
one
two
three
four

Maybe the line is not empty, run cat -vet file to see if there is something.

The new sed version 4.7 has a new option --debug, it is very useful to see how sed works.

Paulo

Posted 2018-12-23T11:58:42.437

Reputation: 606