yPhil
yPhil

Reputation: 8367

regexp (sed) suppress "no match" output

I'm stuck on that and can't wrap my head around it: How can I tell sed to return the value found, and otherwise shut up?

It's really beyond me: Why would sed return the whole string if he found nothing? Do I have to run another test on the returned string to verify it? I tried using "-n" from the (very short) man page but it effectively suppresses all output, including matched strings.

This is what I have now :

echo plop-02-plop | sed -e 's/^.*\(.\)\([0-9][0-9]\)\1.*$/\2/'

which returns 02 (and that is fine and dandy, thank you very much), but:

echo plop-02plop | sed -e 's/^.*\(.\)\([0-9][0-9]\)\1.*$/\2/'

returns plop-02plop (when it should return this = "" nothing! Dang, you found nothing so be quiet! For crying out loud !!)

I tried checking for a return value, but this failed too ! Gasp !!

$ echo plop-02-plop | sed -e 's/^.*\(.\)\([0-9][0-9]\)\1.*$/\2/' ; echo $?
02
0
$ echo plop-02plop | sed -e 's/^.*\(.\)\([0-9][0-9]\)\1.*$/\2/' ; echo $?
plop-02plop
0
$

This last one I cannot even believe. Is sed really the tool I should be using? I want to extract a needle from a haystack, and I want a needle or nothing..?

Upvotes: 28

Views: 14453

Answers (2)

przemoc
przemoc

Reputation: 3869

sed by default prints all lines.

What you want to do is:

/patt/!d;s//repl/

In other words, delete lines not matching your pattern, and for lines that do match, extract particular element from it, giving capturing group number for instance. In your case it will be:

sed -e '/^.*\(.\)\([0-9][0-9]\)\1.*$/!d;s//\2/'

You can also use -n option to suppress echoing all lines. Then line is printed only when you explicitly state it. In practice, scripts using -n are usually longer and more cumbersome to maintain. Here it will be:

sed -ne 's/^.*\(.\)\([0-9][0-9]\)\1.*$/\2/p'

There is also grep, but your example shows why sed is sometimes better.

Upvotes: 34

sehe
sehe

Reputation: 393164

Perhaps you can use egrep -o?

input.txt:

blooody
aaaa
bbbb
odor
qqqq

E.g.

sehe@meerkat:/tmp$ egrep -o o+ input.txt 
ooo
o
o
sehe@meerkat:/tmp$ egrep -no o+ input.txt 
1:ooo
4:o
4:o

Of course egrep will have slightly different (better?) regex syntax for advanced constructs (back-references, non-greedy operators). I'll let you do the translation, if you like the approach.

Upvotes: 2

Related Questions