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..?
sed does not support "non greedy" operator. You have to use "[]" operator to exclude "/" from match. P.S. there is no need to backslash "/".
The "\1" is the first remembered pattern, and the "\2" is the second remembered pattern. Sed has up to nine remembered patterns. This will output "abcd" and delete the numbers. This, when used as a filter, will print lines with duplicated words.
If the sed command fails, for example, if you try to run it on a file you don't have write access to or one that doesn't exist, sed will exit with a non-0 exit status. The exit status just indicates whether sed managed to do what you told it to do, and echo "foo. bar" | sed 's/pop.
sed by default prints all lines.
What you want to do is
/patt/!d;s//repl/
IOW delete lines not matching your pattern, and if they 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With