vimgrep 可以与环视断言一起使用吗?

Can vimgrep be used with lookaround assertions?

我正在尝试在一个大型 JavaScript 项目上自动执行一些文本操作,并希望使用 vimgrep 跳转到匹配项,我将随后调用各种宏。

我的目标行是这样的:

getText("foo", 1)

但是,不是这样的:

getText("foo")
getText("foo", [1])

我只想匹配 getText 的用法,它有一个以上的参数,没有包含在数组中。

此搜索查询 (/) 使用否定的前瞻性,似乎有效:

getText(.*",\(.*[\)\@!

但是,运行 这个正则表达式 vimgrep:

:vimgrep /getText(.*",\(.*[\)\@!/ project/src/**/*.js

...失败并显示此消息:

E682: Invalid search pattern or delimiter

我怀疑我的正则表达式的前瞻部分是原因,因为当我删除它时错误消失了。

有没有办法在 vimgrep 中使用环视断言?

:vimgrep 将每个搜索到的文件加载到 Vim 缓冲区中,然后对其应用 Vim 的正则表达式搜索。因此,与 'grepprg' / :grep 等外部工具不同,您可以在此处使用完整的 Vim 正则表达式语法。

正如@Matt 已经评论的那样,E682 是由于未能转义[ 造成的。当您在常规 / 搜索中使用表达式时,Vim 仅将 [ 视为文字字符,因为 collection 未正确关闭 - 您的搜索工作预期。

但是,

:vimgrep 中,{pattern} 必须用 /.../ 定界符括起来。显然,解析器继续寻找结尾的 /,但找不到它,因为尚未关闭的 [ 集合一直在消耗字符,这会导致错误。这种不一致并不好,它显然让你绊倒了,但它不一定是错的。现在你知道了:-)

只需将 [ 字符正确地转义为 \[,它就会起作用:

:vimgrep /getText(.*",\(.*\[\)\@!/ project/src/**/*.js

有特殊的正则表达式原子(\v and \V)可以改变转义的数量;有些人喜欢使用它们(以避免过度转义,或为了更好的可读性)——我主要发现解释中的必要转变会分散注意力。

@IngoKarkat 直接提问。但是,:vimgrep 在大型项目上可能会很慢,因此如果需要的话最好有一个替代方案。

:grep'grepprg'

Vim 的 :grep:vimgrep 类似,只是它使用外部程序(如 grep)进行搜索。您甚至可以将 'grepprg' 设置为 different tool like: ripgrep, the silver searcher 或 git-grep。使用这些工具通常可以大大加快搜索速度。

set grepprg=rg\ --vimgrep

但是,每个工具都使用自己的正则表达式语法,可能不提供 positive/negative look-ahead/behind 断言。一种方法是使用 :grep 搜索所有条件,然后通过 :Cfilter.

过滤掉不需要的结果
:grep -t js 'getText' project/src/

:Cfilter

:Cfilter /{pat}/ 将允许您使用模式过滤 quickfix 结果。此模式将使用 Vim 的正则表达式语法,因此您可以像往常一样使用您的断言。

:Cfilter /getText(.*",\(.*\[\)\@!/

您可以使用 ! 来否定过滤器,例如:Cfilter! /{pat}/,则使用不匹配 {pat} 的条目。

注意::Cfilter 是一个可选包,您需要执行 :packadd cfilter 来加载插件。

更多帮助

如需更多帮助,请参阅:

:h :grep
:h 'grepprg'
:h :Cfilter