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

时间:2012-08-07 17:39:31

标签: regex perl vim

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

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

看了this post后,我意识到我可以在perl中构建这样的内容:

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

正确匹配前四行。或者,使用this post建议的前瞻构造,可以使用稍微简洁的代码进行匹配:

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\&

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

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

2 个答案:

答案 0 :(得分:5)

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

你最接近\c\(foo\)\@=\(bar\)@=,但是因为你不想要,例如foobarbarfoo以匹配使用单词匹配开头/结尾的必要性:\<\>

使用\&简化了模式。

如果您不需要来自该模式的整个行匹配,只需匹配任何匹配的行,您可以通过删除尾随.*来简化此正则表达式。模式中的碎片:\c.*\<foo\>\&.*\<bar\>

答案 1 :(得分:2)

尝试以下方法:

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

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