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