2012-02-25 150 views
5

我使用正則表達式查找:正則表達式前瞻

test:? 

後跟任意字符直到它擊中了下:

test:? 

現在,當我運行這個正則表達式我做:

((?:test:\?)(.*)(?!test:\?)) 

本文內容:

test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2 

我有望獲得:

test:?foo2=bar2&baz2=foo2 

test:?foo=bar&baz=foo 

test:?foo2=bar2&baz2=foo2 

但是,相反它匹配的一切。有更多正則表達式經驗的人知道我出錯的地方嗎?我以前使用過正則表達式進行模式匹配,但這是我第一次體驗lookarounds/ahead。

預先感謝任何幫助/提示/指針:-)

+0

你只是想拆就'測試:'?如果你是這樣,你的環境將提供一種沒有正則表達式的方式。 – 2012-02-25 00:49:25

回答

4

我想你可以探索一個貪婪的版本。
(擴大)

(test:\? (?: (?!test:\?)[\s\S])*)

+0

謝謝。這工作完美,我學到了更多的語法。 – james 2012-02-25 12:31:11

-1

你可能想((?:test:\?)(.*?)(?=test:\?)),雖然你還沒有告訴我們您正在使用驅動正則表達式是什麼語言。

.*?匹配儘可能少字符作爲可能的,而不防止整個字符串從匹配,其中匹配.*許多越好(是貪婪)。

也取決於您使用何種語言來完成此操作,您可能需要匹配,然後切斷字符串,然後重新匹配,或者調用某種語言特定的match_all類型函數。

順便說一句,你不需要使用一個超前錨定一個正則表達式(你可以匹配模式的搜索,而不是),因此這將(最有可能)你的情況做:

test:[?](.*?)test:[?] 
+1

如果你打算採取這種方法,那麼你需要將'?!'改爲'?='。 – ruakh 2012-02-25 00:49:58

+0

@ruakh對。改變,謝謝。 – Borealid 2012-02-25 00:52:51

+1

-1,需要先行。沒有它,所有其他所需的匹配將不匹配,因爲'test:'已經被使用。 – Qtax 2012-02-25 03:24:48

0

三個問題:

  • (?!)是一種消極的前向斷言。相反,您需要(?=),要求接下來是test:?

  • .*很貪婪;你希望它非貪婪,以便抓住第一個塊。

  • 你也想要最後一個塊,所以你最好也要匹配$

最終結果:

(?:test:\?)(.*?)(?=test:\?|$) 

我也去掉了外組,看到它沒有任何意義。我所知道的所有RE引擎都允許您訪問0組作爲完全匹配,或者其他某種方式(儘管在查找所有匹配項時可能不會)。如果需要,你可以放回去。

(此作品在PCRE,不知道這是否會與POSIX正則表達式工作,因爲我在與他們合作的習慣,我不是。)

如果你只是想拆就test:?,但是,正則表達式是錯誤的工具。使用您的語言對此類內置支持來分割字符串。

的Python:

>>> re.findall('(?:test:\?)(.*?)(?=test:\?|$)', 
... 'test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2') 
['foo2=bar2&baz2=foo2', 'foo=bar&baz=foo', 'foo2=bar2&baz2=foo2'] 
2

的Perl程序如下

#! /usr/bin/env perl 

use strict; 
use warnings; 

$_ = "test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2"; 

while (/(test:\? .*?) (?= test:\? | $)/gx) { 
    print "[$1]\n"; 
} 

產生從你的問題所需的輸出,加上強調括號。

[test:?foo2=bar2&baz2=foo2] 
[test:?foo=bar&baz=foo] 
[test:?foo2=bar2&baz2=foo2]

記住regex quantifiers are greedy,想吞噬儘可能多的,因爲他們可以在不破壞比賽。每個子段儘快終止,這意味着.*?語義。

每個子段終止於另一個test:?或字符串末尾,我們尋找與(?=...)零寬度預覽包圍|替代品。

爲了便於閱讀,上述代碼中的模式使用Perl’s /x regex switch。根據您重新使用的語言和庫,您可能需要刪除多餘的空格。

+0

我在正則表達式測試中使用了你的sytnax,但是這個匹配仍然給了我一個包含兩個「test」的字符串?字符串。我正在使用Java,所以我認爲它可能通過語法相關? (我刪除了用於測試的空格)。感謝您的幫助,雖然我學到了更多。 – james 2012-02-25 12:33:27