2

我正在尝试在一个大型 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

4

2 回答 2

5

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

正如@Matt 已经评论的那样,这E682是由于未能逃脱[. 当您在常规/搜索中使用表达式时,Vim 只是将[视为文字字符,因为集合没有正确关闭 - 您的搜索按预期工作。

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

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

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

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

于 2019-11-22T07:26:27.247 回答
2

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

:grep'grepprg'

Vim:grep与 类似,:vimgrep只是它使用外部程序(如grep)进行搜索。您甚至可以设置'grepprg'不同的工具,例如:ripgrepsilver searcher或 git-grep。使用这些工具通常可以大大加快搜索速度。

set grepprg=rg\ --vimgrep

但是,每个工具都使用自己的正则表达式语法,并且可能不提供正/负前瞻/后置断言。一种方法是使用 搜索所有条件,:grep然后通过 过滤掉不需要的结果:Cfilter

:grep -t js 'getText' project/src/

:Cfilter

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

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

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

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

更多帮助

如需更多帮助,请参阅:

:h :grep
:h 'grepprg'
:h :Cfilter
于 2019-11-22T15:34:47.210 回答