0

I am practicing my sed and regex and am trying to replace all instance of "cheer" with lalaland in the file below, while excluding things like cheering:

ubuntu@ip-172-31-58-40:~$ cat test
cheer
cheering
.
word
cheerytree
acheerytree

ubuntu@ip-172-31-58-40:~$ sed -i "s/cheer[^ing]/lalaland/g" test
ubuntu@ip-172-31-58-40:~$ cat te
cat: te: No such file or directory
ubuntu@ip-172-31-58-40:~$ cat test
cheer
cheering
.
word
lalalandtree
alalalandtree

I don't understand why the first item, cheer, is left along.

Thanks

  • 2
    @DopeGhoti: bash doesn't do this kind of expansion within double quotes; try touch test and then echo "tes[^x]" vs echo tes[^x]. – dhag Feb 9 '17 at 17:32
5

The pattern [^ing] doesn't do what you think it does: it matches one character, which has to be none of i, n, or g.

If your problem can be rephrased as "replace instances of cheer as a whole word", then the following may work, using the marker for word boundaries, \b:

sed 's/\bcheer\b/lalaland/g'
1

The expression [^ing] means any single character except i, n, or g. Hence cheer[^ing] doesn't match in the case of cheer alone because there is no additional character to match (or not match).

What you seem to be trying to implement is negative lookahead i.e. a zero length assertion that matches cheer except where it is followed by the string ing. That's not straightforward in sed but is relatively easy in perl using the syntax (?!ing) i.e.

perl -pe 's/cheer(?!ing)/lalaland/g' test
lalaland
cheering
.
word
lalalandytree
alalalandytree

See Lookahead and Lookbehind Zero-Length Assertions

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.