6

How can I restrict find and replace to replace items, but not if the character immediately before it is "A", "B", or "C" or the character immediately after it is "X", "Y", or "Z". E.g. given these input lines, if "cat" is to be replaced with replaced with "pet":

  • "There is a cat." → "These is a pet."
  • "There is Acat." is unchanged, because "A' is found before.
  • "There is catY." is unchanged, because "Y' is found after.
  • "There is CcatX." is unchanged, because "C' is found before and "X" after.
Village
  • 22,513
  • 46
  • 122
  • 163

4 Answers4

4

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
anubhava
  • 761,203
  • 64
  • 569
  • 643
3

This might work for you (GNU sed):

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

or:

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

or in light of comments:

sed -r 's/(\b|[^ABC])cat(\b|[^XYZ])/\1pet\2/g' file
potong
  • 55,640
  • 6
  • 51
  • 83
2

Assuming your text is in a file called text.txt. This will work:

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

What is happening (from tutorialspoint.com, man sed and 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.
cforbish
  • 8,567
  • 3
  • 28
  • 32
1

Using might be a better idea since it supports lookahead/lookbehind:

perl -lape 's/(?<![ABC])cat(?![XYZ])/pet/' input
perreal
  • 94,503
  • 21
  • 155
  • 181