3

我正在尝试搜索包含一组单词的任何排列的行(不区分大小写)。例如,如果我对fooand感兴趣bar,我想匹配前四行,而不是下面的最后四行file

Foo and bar.
Bar and foo.
The foo and the bar.
The bar and the foo.
Foobar.
Barfoo.
The foobar.
The barfoo.

看过这篇文章后,我意识到我可以在以下位置构建类似的东西perl

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

仅正确匹配前四行。或者,使用本文建议的前瞻结构,可以使用更简洁的代码进行匹配:

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

但是,我无法弄清楚如何用vim正则表达式语法编写这些,我发现它比perl正则表达式语法更加拜占庭式。我在vim使用搜索功能(/?)时尝试了许多不同的表达式,但没有一个能产生成功的匹配。我意识到,而不是使用的(?=string)语法perlvim使用\(string\)\@=string\&

然而,各种尝试,例如:

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

(where\c用于不区分大小写的匹配)都失败了。

有人可以演示正确的vim语法吗?

4

2 回答 2

5

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

您与 最接近\c\(foo\)\@=\(bar\)@=,但由于您不希望 egfoobar进行barfoo匹配,因此有必要使用单词匹配的开头/结尾:\<\>

使用\&稍微简化了模式。

如果您不需要该模式的行匹配,只需点击匹配的任何行,您可以通过消除模式中的尾随.*部分来进一步简化此正则表达式:\c.*\<foo\>\&.*\<bar\>

于 2012-08-07T17:45:53.570 回答
2

尝试以下操作:

/^\c\(.*\<foo\>\)\@=\(.*\<bar\>\)\@=/

这与 Perl 的前瞻版本相同,\@=使前一个元素或组成为正前瞻。 \<\>是 vim 等价于\b, 并\c启用不区分大小写的匹配。我添加了^锚点,因此它只会匹配每一行一次。

于 2012-08-07T17:46:07.657 回答