vim 命令模式下的引用和转义

vim quoting and escaping in command mode

我正在尝试在 Vim (https://thoughtbot.com/blog/faster-grepping-in-vim) 中使用 ag(银色搜索器)。我试图更花哨一点,并创建一个自定义命令来仅搜索与某些文件扩展名匹配的文件。 IE。使用 ag 支持的 -G regex 模式。

除了试图为此创建一个映射之外,这行得通,但我发现我无法很好地处理这种情况下的引用。

链接的文章显示了如下映射: nnoremap K :grep! "\b<C-R><C-W>\b"<CR>:cw<CR>

我想要第二个,它只检查项目中的 C 文件。 类似这样的东西,除了这不起作用,因为我无法弄清楚所需的引用:

nnoremap ,k :grep! "\b<C-R><C-W>\b" . '-G \.+(h<Bar>c)$'<CR>:cw<CR>

欢迎来到这个特别混乱的地狱。

让我们从在 shell 中使用的正确命令开始:

$ ag "\bfoo\b" -G '\.+(h|c)$'

假设我们的 vimrc 中有以下行,如链接 post 中的说明:

set grepprg=ag\ --nogroup\ --nocolor

如果我们尝试在 :help :grep 中按原样使用 -G 标志:

:grep! "\bfoo\b" -G '\.+(h|c)$'

我们从 Vim:

得到这个
:!ag --vimgrep "\bfoo\b" -G '\.+(h 2>&1| tee /var/folders/_d/bdwh8scx4hb1v2w__l0x6nk19ndqk1/T/vcaYrBc/6

这个,来自bash:

/bin/bash: -c: line 0: unexpected EOF while looking for matching `''
/bin/bash: -c: line 1: syntax error: unexpected end of file

最后是这个,来自 Vim:

E426: tag not found: c)$

这告诉我们 a) 模式在到达 ag 之前被缩短了 b) 命令的某些部分甚至在执行外部命令后到达 Vim,这不是在这一点上是可取的。

问题是 h|c 中的 | 被 Vim 解释为命令分隔符,所以我们将命令的一部分发送到 shell 和Vim 的另一部分,一切都坏了,因为两个程序都阻塞了我们发送给它们的内容。

这很容易解决,只需转义栏即可:

:grep! "\bfoo\b" -G '\.+(h\|c)$'

而且有效!

但不在映射中:

nnoremap ,k :grep! "\b<C-r><C-w>\b" -G '\.+(h\|c)$'<CR>:cw<CR>

我们还需要一个反斜杠:

nnoremap ,k :grep! "\b<C-r><C-w>\b" -G '\.+(h\|c)$'<CR>:cw<CR>

因为 \| 在此上下文中扩展为 |,因此需要第二个反斜杠以确保我们得到实际的 \|。参见 :help map-bar

我们完成了。


请注意,您可以使用 --cc 作为 -G '\.+(h|c)$' 的替代方法。