如何使用sed查找并替换不带特定字符前缀或后缀的项?

6

如何限制查找和替换以替换项目,但不替换前面紧跟着"A"、"B"或"C"或后面紧跟着"X"、"Y"或"Z"的字符。例如,给定以下输入行,如果要用"pet"替换"cat":

  • "There is a cat." → "These is a pet."
  • "There is Acat." 不变,因为在前面找到了"A"。
  • "There is catY." 不变,因为在后面找到了"Y"。
  • "There is CcatX." 不变,因为在前面找到了"C"并且在后面找到了"X"。
4个回答

4
这个sed命令应该适用于你的情况:
sed -r 's/(^|[^ABC])cat\>/\1pet/g; s/\<cat([^XYZ]|$)/pet\1/g' file

测试:

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

测试使用 猫是猫是猫 - cforbish
我使用该输入进行测试,并得到以下结果:pet is a pet is a pet - anubhava
我得到了 宠物是猫是宠物。不过我还是给你点了个赞。 - cforbish

3
这可能适合您(GNU sed):
sed 's/\bcat\b/pet/g' file

或者:

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

或者考虑评论的建议:
sed -r 's/(\b|[^ABC])cat(\b|[^XYZ])/\1pet\2/g' file

根据 OP 的说法,“there are cats” 应该变成 “there are pets”,但这段代码并没有实现这个功能。 - anubhava

2
假设您的文本存储在名为text.txt的文件中,以下方法可行:
sed -i 's/\(.*[^ABC]\|^\)cat\([^XYZ].*\|$\)/\1pet\2/g' text.txt

发生了什么事情(来自 tutorialspoint.comman sedsed 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.

使用输入cat is a cat进行测试 - anubhava

1

使用 可能是一个更好的主意,因为它支持向前/向后查找:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接