Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sed can't match 0 or 1 time

Tags:

bash

shell

sed

I'm writing a bash script on Cent OS7. Now I need to use sed to remove all lines which don't contain .jpg or .jpeg.

Here is my script:

sed -i -e '/\.jp(e)?g/!d' myfile

But it will delete all lines, which means that it doesn't work as expected.

However, if I do sed -i -e '/\.jpg/!d' myfile or sed -i -e '/\.jpeg/!d' myfile. Both of them work well.

like image 462
Yves Avatar asked Jun 01 '17 05:06

Yves


People also ask

When does SED return 0 or 1?

sed Q uits input just as soon as the very first match is found anywhere in the file - which means it does not waste any more time continuing to read the infile. sed returns in its exit code the numeric value 0 or 1 depending on whether it couldn't/could find the addressed regexp. $i is set to sed 's return upon exit.

What happens if no match is found in SED?

If no match is found, the variable will be set as i=0. Show activity on this post. Show activity on this post. sed (Stream EDitor) is not the right tool for this kind of things: you can simply use a bash if statement to match your input against a regex:

Why does SED quit after reading a regexp?

Some facts about this answer: sed Quits input just as soon as the very first match is found anywhere in the file - which means it does not waste any more time continuing to read the infile. sed returns in its exit code the numeric value 0 or 1 depending on whether it couldn't/could find the addressed regexp.

How does SED query work?

sed Q uits input just as soon as the very first match is found anywhere in the file - which means it does not waste any more time continuing to read the infile. sed returns in its exit code the numeric value 0 or 1 depending on whether it couldn't/could find the addressed regexp.


1 Answers

Captured group (()) and the quantifier ? (match the preceding token 0 or 1 time) comes (at least) with ERE (Extended RegEx), not BRE (Basic RegEx).

sed by default uses BRE, so the tokens are being treated literally.

To enable ERE, use -E (or -r if available) with sed:

sed -E '/\.jp(e)?g/!d' myfile

Capturing e is redundant here:

sed -E '/\.jpe?g/!d' myfile

Note that, you can use ERE tokens from BRE by escaping them with \, so the following would work too:

sed '/\.jp\(e\)\?g/!d' myfile
sed '/\.jpe\?g/!d' myfile

Again, this does not look as clean as just using one option i.e. -E. Only case where you will want this is portability.

like image 140
heemayl Avatar answered Oct 27 '22 21:10

heemayl