2012-08-07 71 views
3

我正在嘗試搜索包含任何一組字詞(不區分大小寫)的排列的行。例如,如果我感興趣的話foobar,我想前四線,但在以下file不是最後四行匹配:vi中包含字符串集合的任意排列的匹配行

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中嘗試了許多不同的表達式,但沒有一個產生成功匹配。我意識到,代替perl使用的(?=string)語法,vim使用\(string\)\@=string\&

然而,各種嘗試,例如:

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

(其中\c用於不區分大小寫匹配)已經全部不成功。

有人能請示範正確的vim語法嗎?

回答

5

嘗試:\c.*\<foo\>.*\&.*\<bar\>.*。這應該匹配前四行中的每一行。

您與\c\(foo\)\@=\(bar\)@=最接近,但由於您不希望foobar,barfoo以匹配它是必要的使用詞匹配的開始/結束:\<\>

使用\&簡化了一下模式。

如果您不需要整個線從模式匹配,只是砸在任何匹配線路,可以簡化這個表達式多一點由圖案殺死後.*件:\c.*\<foo\>\&.*\<bar\>

+0

謝謝,這兩個匹配正確,每行只有一次。 – user001 2012-08-07 18:21:05

2

嘗試以下操作:

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

這是同樣的事情,從Perl的先行版本,\@=使得前一個元素或組正向前查找。 \<\>是相當於\b的vim,而\c支持不區分大小寫的匹配。我添加了^錨點,因此它只會匹配每行一次。

+0

謝謝,'^'錨點非常有用,因爲如果沒有它,則該行中的每個字符都被視爲唯一匹配。你能否告訴我如何添加一個可選的後綴?說,我想匹配禁止和禁止。我意識到我可以省略單詞結束邊界('/^\ c \(。* \ \)\ @ = \(。* \ '那樣匹配? – user001 2012-08-07 18:18:50

+2

關閉,但更多的轉義:'\ <酒吧\(ed \ | ing \)\>' – pb2q 2012-08-07 18:39:20

相關問題