5

抱歉,如果这已经发布,因为我找不到答案,即使在 vim wiki 上也是如此。

有没有一种方法可以在 vim 命令行模式下通过一次:g搜索运行多个命令?

例如,

:%g/foo/ s/bar/\=@a/g | exe "norm /cat\<enter>\"ayiw"

哪个(对于我打算做的事情)应该在每一行 matchfoo上替换bar为 register 的内容a然后找到下一次迭代cat(即使它前面有很多行),并将周围的单词放入 register a

相反,此特定语法使用初始寄存器的当前内容a完成替换命令,然后在单行上执行正常模式命令(在完成替换之后)。

此示例不是我的特定用例,但显示了此功能有用的一个实例。我意识到我可以把它全部放在一个单一exe的 ie, 中%g/foo/exe "norm :s/bar/\\=@a/g\<enter>/cat\<enter>\"ayiw",但我想用第一种方式来做,因为我觉得它更灵活。


我更喜欢使用 vanilla vim 来执行此操作,但如果存在为此的插件,那是一个不错的选择。有谁知道是否有语法来做这样的事情?

4

2 回答 2

1

您可以这样做(至少对于应用于单个 :g 的多个 :s 命令)。例子:

" SHORT STORY TITLES to single word of CapitalizedWords within <h3>s
.,$g/^\L\+$/s/[^A-Z0-9 ]\+//ge|s/\u\+/\L&/ge|s/\<\l\+\>/\u&/ge|s/ \+//ge|s/.*/<h3>&<\/h3>/
于 2018-12-04T22:15:25.910 回答
1

好吧,有点“脏”,但这对你有用吗?

:let list = split(execute('g/cat/p'), '\n') | g/foo/ s/bar/\=matchstr(remove(list, 0), '\s\d\+\s\zs.*')/g

它首先读取所有出现的cat将它们保存在列表中。然后用bar第一只猫替换第一个......等等。

肮脏的部分是matchstr命令。还为g//p结果返回一个数字,因此列表如下所示:

 1 cat
 2 cat
 3 cat
 ...

这就是为什么我们必须从前面移除一点。我很想知道是否有人知道一个干净的解决方案(我也对一个干净的 vimscript 解决方案感兴趣,不必是 oneliner)。

于 2017-08-03T11:38:50.157 回答