用Sed将连字符替换为下划线

4

我是一名新手对正则表达式有些困惑。我希望在文件中特定的位置将连字符替换成下划线。为了简化问题,让我们假设我只想替换第一个连字符。以下是一个示例 "文件":

dont-touch-these-hyphens
leaf replace-these-hyphens

我希望将所有行中的连字符替换为

grep -P "leaf \w+-" file

我尝试了

sed -i 's/leaf \(\w+\)-/leaf \1_/g' file

但是什么都没有发生(错误的替换比什么都没有要好)。我尝试了一些调整,但仍然没有效果。再次说明,我是新手,所以我认为上面的“基本上应该可以工作”。它有什么问题,我该如何得到我想要的结果?谢谢。


4
你没有使用支持 \w 的正则表达式扩展。你需要使用 sed -Esed -r - stevesliva
像这样吗?sed -i -E 's/leaf (\w+)\-/leaf \1_/g' 文件 - Erik Vesterlund
2
@stevesliva GNU sed 就像那样理解 \w。对于 GNU sed,sedsed -E(或 sed -r)之间唯一的区别是你需要转义的内容不同。详见官方文档 - Benjamin W.
@BenjaminW. 你是对的。需要扩展正则表达式来处理 +。抱歉,我有一把锤子,看起来所有东西都像钉子。解决方案正确,但推理错误。 - stevesliva
1
@stevesliva GNU sed甚至为基本正则表达式提供了一个扩展:\ +具有与扩展正则表达式中的+相同的效果。 除引号外,它们确实是等价的。BRE中的\(\) \{\} \+ \? \|', ERE中的() {} +?|'。 - Benjamin W.
现在看起来就像看油漆干一样,不是钉子... :D - stevesliva
2个回答

6

您可以使用两个不同的正则表达式来简化操作,一个用于匹配需要处理的行,另一个用于匹配需要修改的内容。

您可以尝试如下方法:

$ sed '/^leaf/ s/-/_/' file
dont-touch-these-hyphens
leaf replace_these-hyphens

不错!那怎么实现的?如果我没有弄错,第一部分是“不匹配字符leaf”,但除此之外呢? - Erik Vesterlund
3
对于以"leaf"开头的行,进行替换。 - stevesliva
4
在这里,^是“行首”锚点,而不是字符类中的否定符号。 - Benjamin W.

1

只需使用awk:

$ awk '$1=="leaf"{ sub(/-/,"_",$2) } 1' file
dont-touch-these-hyphens
leaf replace_these-hyphens

它可以让你更精确地控制你所匹配的内容(例如上面的示例是对字符串而不是正则表达式进行匹配,因此即使该字符串包含类似于 .* 的正则表达式元字符,它也能正常工作),以及你所要替换的内容(例如上面的示例仅在 leaf 之后的文本中进行替换,因此即使 leaf 本身包含 -,它也会继续正常工作):
$ cat file
dont-touch-these-hyphens
leaf-foo.*bar replace-these-hyphens
leaf-foobar dont-replace-these-hyphens

正确输出:

$ awk '$1=="leaf-foo.*bar"{ sub(/-/,"_",$2) } 1' file
dont-touch-these-hyphens
leaf-foo.*bar replace_these-hyphens
leaf-foobar dont-replace-these-hyphens

错误输出:
$ sed '/^leaf-foo.*bar/ s/-/_/' file
dont-touch-these-hyphens
leaf_foo.*bar replace-these-hyphens
leaf_foobar dont-replace-these-hyphens

注意,leaf-foo中的“-”在最后两行(包括不以“leaf-foo.*bar”字符串开头的那一行)中被替换为“_”。
该awk脚本可在任何UNIX框架上使用任何awk而不需修改。

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