我想在Vim中找到一个很好的方法来执行此搜索并替换以下内容 -
name_1
end
name_2
end
name_3
end
我将name_“x”添加到其后面的“end”语句中。所以它看起来像这样 -
name_1
end_name_1
name_2
end_name_2
name_3
end_name_3
注意 - name_3之前的空行会破坏“name_x”和“end”之间的常量行间距。所以我想的是像
这样的东西:g/\(name_x\)/,/end/ s/end/end_\1/
现在尝试存储第一个模式并不起作用,但希望你能得到这个想法。这里有什么技巧吗?
由于
答案 0 :(得分:3)
您遇到的问题是\1
是指当前替换的匹配组而不是:g
命令的模式。遗憾的是,您无法访问之前搜索中的先前匹配组。然而,有一些方法可以实现您的目标。我建议的第一个是宏。
首先在非匹配线上开始。这可以通过在需要时在文件顶部插入一个空行来完成(之后只需将其删除)。
/name_\d\+
y//e
/end/e
a_
p
q
999@q
这是我使用的宏:
:let @q = "/name_\\d\\+\<cr>y//e\<cr>/end/e\<cr>a_\<esc>p"
另一种方法是以与您的尝试类似的方式使用:global
命令。
:g/name_\d\+/let @@=matchstr(getline('.'),'name_\d\+')|/end/s//\=submatch(0).'_'.@@/
我个人认为这太复杂了,但有选择权很好。该命令可以分为以下几部分:
:g/name_\d\+
在每行匹配name_和一些数字getline('.')
将返回当前行的字符串matchstr(getline('.'), 'name_\d\+')
将仅返回当前行的匹配部分let @@ = matchstr(...)
会将匹配的部分设置为默认寄存器/end/s/
会在与:s
匹配的以下行执行end
s//\=.../
与上次使用的模式匹配,并将其替换为快速。submatch(0).'_'.@@
创建一个字符串,其中包含整个匹配的模式,后跟下划线和未命名寄存器的内容。有关以下主题的更多信息,请参阅:
:h q
:h search-offset
:h :g
:h :let-@
:h registers
:h matchstr(
:h getline(
:h range
:h submatch(