134

如何使用 sed 搜索和替换整个单词?

正在做

sed -i 's/[oldtext]/[newtext]/g' <file> 

还将替换[oldtext]我不希望这样做的部分匹配项。

4

5 回答 5

186

正则表达式中的 \b 匹配单词边界(即第一个单词字符和非单词字符之间的位置):

$ echo "bar embarassment" | sed "s/\bbar\b/no bar/g"
no bar embarassment
于 2009-06-23T11:41:16.600 回答
154

在 Mac OS X 上,这些正则表达式语法在sed中都不能用于匹配整个单词

  • \bmyWord\b
  • \<myWord\>

现在听我说,以后再相信我,这个丑陋的语法是你需要使用的:

  • /[[:<:]]myWord[[:>:]]/

因此,例如,仅在整个单词中用mint替换mint :

  • sed "s/[[:<:]]mint[[:>:]]/minty/g"

来源:re_format 手册页

于 2011-04-20T17:27:44.903 回答
15

用于\b单词边界:

sed -i 's/\boldtext\b/newtext/g' <file>
于 2009-06-23T11:42:39.920 回答
8

在我的一台机器上,用“ \b”(不带引号)分隔单词不起作用。解决方案是使用“ \<”作为起始分隔符,“ \>”作为结束分隔符。

Joakim Lundberg的例子来解释:

$ echo "bar embarassment" | sed "s/\<bar\>/no bar/g"
no bar embarassment
于 2010-03-16T22:44:12.123 回答
0

对于符合 posix 的替代方案,请考虑将单词边界匹配 ( \b) 替换为扩展的等效项 ( [^a-zA-Z0-9]),同时考虑在行首 ( ^) 和行尾 ( $) 的出现。

但是,如果您想支持重复出现的要替换的单词(例如oldtext oldtext),这很快就会变得不切实际。sed --posix不识别诸如 的表达式\(^\|[^a-zA-Z0-9]\),并且您不能使用环视。

看来我们必须明确匹配所有可能的情况。mint这是替换为的解决方案minty

echo 'mint 0mint mint mint0 mint__mint mint__ mint_ -mint mint mint mint_ mint -mint- mint mint mintmint mint' \
  | sed --posix '   
s/^mint$/minty/g;
s/^mint\([^a-zA-Z0-9]\)/minty\1/g;
s/\([^a-zA-Z0-9]\)mint$/\1minty/g;
s/\([^a-zA-Z0-9]\)mint\([^a-zA-Z0-9]\)mint\([^a-zA-Z0-9]\)mint\([^a-zA-Z0-9]\)/\1minty\2minty\3minty\4/g;
s/\([^a-zA-Z0-9]\)mint\([^a-zA-Z0-9]\)mint\([^a-zA-Z0-9]\)/\1minty\2minty\3/g;
s/\([^a-zA-Z0-9]\)mint\([^a-zA-Z0-9]\)/\1minty\2/g;
'
# minty 0mint minty mint0 minty__minty minty__ minty_ -minty minty minty minty_ minty -minty- minty minty mintmint minty
于 2021-09-25T13:58:02.627 回答