我想要做这件事:
%s/shop_(*)/shop_\1 wp_\1/
为什么 shop_(*)
没有匹配到任何内容?
在vim正则表达式中,括号不是用来捕获的 -- 你需要使用 \( \)
来捕获。
*
不是你想象中的意思。它的意思是“前面的字符出现0次或多次”,因此你的正则表达式的意思是“一个包含 shop_
后跟0个或多个 (
和一个字面量 )
的字符串”。
你要找的是 .
,在正则表达式中它表示“任何字符”。与星号一起组合成 .*
表示“0个或多个任何字符”。你可能想至少匹配一个字符,所以使用 .\+
(+
表示“前面的字符出现1次或多次”)
使用这个: %s/shop_\(.\+\)/shop_\1 wp_\1/
。
最后一个斜杠后面可以选择加上 g
,这样就会替换一行中的所有实例而不仅仅是第一个实例。
*)
,而只是字面上的 )
。 - Stephen\(re\)\?move
以匹配'move'和'remove'),而不是转义任何应该按字面意义理解的内容。 - Luc如果我理解正确,您想要的是%s/shop_\(.*\)/shop_\1 wp_\1/
转义捕获括号并使用.*
匹配任意数量的任何字符。
(您的搜索正在查找以“ shop_”开头的任意数量的左圆括号后跟一个右圆括号)
如果你想避免不得不转义捕获括号,并使正则表达式模式语法更接近其他实现(例如PCRE),请在模式开头添加\v
(非常神奇!)(有关更多信息,请参见:help\magic
):
:%s/\vshop_(*)/shop_\1 wp_\1/
如果你看这里:regex-info,@Luc,你会发现vim的行为是正确的。这里有一个来自sed的并行例子:
echo "123abc456" | sed 's#^([0-9]*)([abc]*)([456]*)#\3\2\1#'
sed: -e expression #1, char 35: invalid reference \3 on 's' command's RHS
而使用“转义”括号,则可以正常工作:
echo "123abc456" | sed 's#^\([0-9]*\)\([abc]*\)\([456]*\)#\3\2\1#'
456abc123
我不喜欢看到Vim被诋毁 - 特别是当它表现正确时。
PS 我试图将其添加为评论,但无法正确格式化。
%s/shop_/& wp_\1
- nnyby