在vi中匹配包含一组字符串的任何排列的行

use*_*001 3 regex vim perl

我试图搜索包含一组单词的任何排列的行(不区分大小写).例如,如果我感兴趣的话foobar我想的第一四行,但在下面的不是最后四行匹配file:

Foo and bar.
Bar and foo.
The foo and the bar.
The bar and the foo.
Foobar.
Barfoo.
The foobar.
The barfoo.
Run Code Online (Sandbox Code Playgroud)

看了这篇文章,我意识到我可以构建这样的东西perl:

perl -n -e 'print if (/\bfoo\b.*?\bbar\b/i || /\bbar\b.*?\bfoo\b/i)' file
Run Code Online (Sandbox Code Playgroud)

它正确匹配前四行.另外,使用由提出前瞻构建这个帖子,比赛可以用稍微更简洁的代码做:

perl -n -e 'print if (/(?=.*\bfoo\b)(?=.*\bbar\b)/i)' file
Run Code Online (Sandbox Code Playgroud)

但是,我不能弄清楚如何用vim正则表达式语法编写它们,我发现它比perl正则表达式语法要多得多.我在vim使用搜索功能(/?)时尝试过很多不同的表达方式,但是没有一个能够产生成功的匹配.我意识到,而不是(?=string)使用的语法perl,vim使用\(string\)\@=string\&.

但是,各种尝试,例如:

  • \c\(foo\)\@=\(bar\)@=
  • \c\(foo\)\@=\.*\(bar\)@=
  • \cfoo\&bar\&

(\c用于不区分大小写的匹配)都不成功.

有人可以证明正确的vim语法吗?

pb2*_*b2q 5

试试:\c.*\<foo\>.*\&.*\<bar\>.*.这应该匹配前四行中的每一行.

你最接近\c\(foo\)\@=\(bar\)@=,但因为你不想要,例如foobar,barfoo匹配它是必要的使用单词匹配的开始/结束:\<\>.

使用\&简化了模式.

如果你不需要来自该模式的行匹配,只需匹配任何匹配的行,你可以通过杀死模式中的尾随.*部分来简化这个正则表达式:\c.*\<foo\>\&.*\<bar\>