2010-06-09 35 views
1

我想匹配一行文本末尾的可選標記。帶可選部分的正則表達式不會創建反向引用

示例輸入文本:

The quick brown fox jumps over the lazy dog {tag} 

我想匹配在大括號的部分,並創建一個向後引用它。

我正則表達式是這樣的:

^.*(\{\w+\})? 

(有些簡化,我也匹配標記之前部分):

就OK線匹配(有和沒有標記),但沒有按不會創建對標籤的反向引用。

如果我刪除'?'字符,所以正則表達式是:

^.*(\{\w+\}) 

它創建一個反向引用標籤,但不匹配沒有標籤的行。

我從http://www.regular-expressions.info/refadv.html理解的是,可選的操作不會影響到反向引用:

輪支架組之間的正則表達式。它們捕獲內部正則表達式匹配的文本,這些文本可以在反向引用中重用,並且允許您將正則表達式運算符應用於整個分組正則表達式。

但是一定是誤會了一些東西。

如何使標籤部分可選並在存在時創建反向引用?

+1

您使用哪種語言? – 2010-06-09 18:46:42

+0

使用C#/ .NET與System.Text.RegularExpressions類。 – user3891 2010-06-09 18:49:38

回答

3

這不是一個反向引用問題,問題在於正則表達式通過在與.*匹配的文本中讀取而得到滿足。它沒有必要繼續閱讀閱讀可選的結束標籤。如果您真正閱讀到行尾,最簡單的解決方案是追加$(美元符號)以強制正則表達式匹配整行。

編輯

順便說一句,我沒從字面上,因爲你說它匹配其他的東西,但僅僅是明確.*會消耗整條生產線把你的REG-EX。你需要像[^{]*這樣的東西來防止標籤被吞下。我猜這對你來說不是問題。

+0

'。* * * * *已經匹配整行。 – Gumbo 2010-06-09 18:53:27

+0

@Gumbo,@padriagf在他的問題中說,問題中的正則表達式更復雜,所以它可能會或可能不會消耗標記。我試圖說清楚他需要檢查。 – 2010-06-09 18:59:18

2

除了別人怎麼解釋,你可能想使.*「懶」:

^.*?(\{\w+\})? 
+0

或者「不貪心」是另一個詞* * - 它總是試圖找到儘可能最短的匹配(而不是最長的匹配) – gnarf 2010-06-09 18:59:49

+0

儘管這實際上不起作用 - 請參閱我的答案。懶惰的量詞將不匹配。你可以[自己嘗試](http://www.rubular.com/r/hjknUHyFQ7)。 – 2010-06-09 19:03:36

1

正如David Gladfelter說,實際的問題是,當你把它可選的,它不匹配;但是,他提出的修復方法將不起作用編輯1:您需要使用他在編輯時所寫的內容(在撰寫本文時已寫入)。問題是量詞(*,+,?,{n,m})是貪婪:他們總是儘可能匹配他們可能。因此,當您編寫^.*(\{\w+\})?時,.*將始終與整行匹配,因爲空匹配滿足可選組。還要注意,儘管?是貪婪的,但第一個貪婪(.*)優先。如果您只允許在該可選組附近使用大括號,則可以通過明確說明來解決您的問題:^[^\{]*(\{\w+\})?。這樣,第一個塊將匹配第一個花括號中的所有內容,然後(因爲?是貪婪的)與捲曲括號中的單詞匹配(如果可以)。

通常,另一種方式來解決,這是通過附加一個?使量詞懶惰(或非貪婪,最小等):*?+???,和{n,m}?。但是,這不會對您有所幫助:相反,如果您執行^.*?(\{\w+\})?,則懶惰.*?將嘗試匹配零個字符,成功,然後可選組不匹配。儘管如此,它在這裏不起作用,但它是您工具箱中的一個有用工具。 編輯1:另外,請注意,這些在所有的正則表達式引擎中都不可用,儘管它們在C#中可用。

1

謝謝你們。我用的回答,不貪婪修改和最終的線比賽,這似乎這樣的伎倆的組合,所以現在正則表達式是:

^.*?(\{\w+\})?$ 

我不想使用[^ { ] *爲比賽的第一部分,因爲非標記大括號可能出現在這裏,但標記將始終在該線的末尾。

感謝您的回答,他們都很有幫助。

0

如果你只在標籤感興趣,並不關心字符串的休息,那麼你最好讓你的生活更容易通過只是這個表達式(see it on rubular.com)相匹配的標籤:

\{(\w+)\}$ 

也就是說,你試圖在字符串的末尾匹配一些{word}。如果它不在那裏,那麼太糟糕了,沒有匹配。不需要?修飾符或不願意的.*以及所有這些東西。

在C#中,你甚至可能要使用RegexOptions.RightToLeft,因爲你想反正匹配後綴,所以也許是這樣的:

string[] lines = { 
    "The quick brown fox jumps over the lazy dog", 
    "The quick brown fox jumps over the lazy dog {tag}", 
    "The quick brown fox jumps over the {lazy} dog", 
    "The quick brown fox jumps over the {lazy} {dog}", 
}; 

Regex r = new Regex(@"\{(\w+)\}$", RegexOptions.RightToLeft); 

foreach (string line in lines) { 
    Console.WriteLine("[" + r.Match(line).Groups[1] + "]"); 
} 

此打印(as seen on ideone.com):

[] 
[tag] 
[] 
[dog]