How to find and replace elements that were not preceded or accompanied by certain characters with sed?

How can I limit the search and replace to replace elements, but not if the character before it is “A”, “B” or “C” or the character immediately after “X”, “Y”, or “Z”. For example. given these input lines, if we replace "cat" with "pet":

  • "There is a cat." → "This is a pet."
  • "There is Akat." does not change because "A" is earlier.
  • "There is catY." does not change because after "Y" is found.
  • "There is CcatX." does not change, because "C" is before and "X" after.
+4
source share
4 answers

This sed should work for you:

sed -r 's/(^|[^ABC])cat\>/\1pet/g; s/\<cat([^XYZ]|$)/pet\1/g' file

Testing:

sed -r 's/(^|[^ABC])cat\>/\1pet/g; s/\<cat([^XYZ]|$)/pet\1/g' <<< 'cat is a cat is a cat'
pet is a pet is a pet
+4
source

This may work for you (GNU sed):

sed 's/\bcat\b/pet/g' file

or

sed 's/\<cat\>/pet/g' file

or in the light of the comments:

sed -r 's/(\b|[^ABC])cat(\b|[^XYZ])/\1pet\2/g' file
+3
source

, text.txt. :

sed -i 's/\(.*[^ABC]\|^\)cat\([^XYZ].*\|$\)/\1pet\2/g' text.txt

( tutorialspoint.com, man sed sed regex):

-i         Edit files in place (makes backup if extension supplied)
s/???/???/ Or s/regexp/replacement/, Attempt to match regexp against the pattern space.
/          Field separator to 's'.
^          Match first character on line.
\(         Start back reference.
.          Match any character.
[^ABC]     Do not match any charcter (^ = don't) in this list.
\|         Matches regex1 or regexp2 (do not match ABC or match start of line).
\)         End back reference.
cat        Match cat
\1         The first back reference.
\2         The second back reference.
g          Replace all matches, not just the first match.
+2

, lookahead/lookbehind:

perl -lape 's/(?<![ABC])cat(?![XYZ])/pet/' input
0

All Articles