2013-07-29 45 views
5

我剛剛在http://regexcrossword.com/上做了有趣的正則表達式填字遊戲 - 發現我不明白量化組的含義。 ()()+或*正則表達式,組和量化器

讓我嘗試http://ole.michelsen.dk/tools/regex.html,它提供的JavaScript和PHP的正則表達式引擎:「Trololo」

來匹配的字符串是(不帶引號)。 (如果對「環球比賽」改變的東西,它被添加作爲底漆版本,也就是JS」,因爲它並沒有改變PHP模式東西。切換)

JS, (.)+ => 0: Trololo! 1: ! 
JS', (.)+ => 0: Trololo! 
PHP, (.)+ => 0: Trololo! 0: ! 
JS, (.)* => 0: Trololo! 1: ! 
JS', (.)* => 0: Trololo! 
PHP, (.)* => 0: Trololo! 1: 0: ! 1: 
JS, (.){5} => 0: Trolo 1: o 
JS', (.){5} => 0: Trolo 
PHP, (.){5} => 0: Trolo 0: o 
JS, (.){4} => 0: Trol 1: l 
JS', (.){4} => 0: Trol 1: olo! 
PHP, (.){4} => 0: Trol 1: olo! 0: l 1: ! 

是否有任何規範性的答案是什麼這是什麼語義?

+0

什麼是JS和JS?有什麼不同? –

+1

我認爲該網站沒有給你正確的羣體。改爲使用http://www.regexplanet.com/。 –

回答

3

輸出沒有正確標記,就這些了。

首先,應該發生什麼?如果您重複一個組,則每個新實例都將覆蓋上次捕獲。如果該組完全不使用,它將返回一個空字符串或類似於JS中的undefined(取決於風格)。關於這個問題,關於regular-expressions.info有一篇很好的文章。

現在我們該如何獲得您的結果?我們從JavaScript開始。

所有標記爲JS(非全局函數)的示例都符合上述說明。它們匹配0中所需的字符數量並捕獲1中的最後一個字符。所以我們可以忽略這些。

什麼是全球性的?這裏的輸出解釋不正確。當您在String.match()函數中使用全局標誌時,您不會再獲取所有捕捉的數組 - 但只有所有匹配的數組(每個匹配組爲0)。因此,在+,*{5}的情況下,只有一個匹配,你只能得到那一個結果。使用{4}時,目標字符串中有足夠的空間用於兩個匹配項,所以生成的數組包含兩個元素。要獲得全局標記的所有捕獲,您需要編寫一個循環,並使用RegExp.exec()來代替(一次給出一個匹配,但是它的所有捕獲)。

什麼是PHP?它似乎使用preg_match_all,這是全球性的,這就是爲什麼使用g沒有效果。 +給出了您期待的結果。 {5}也是如此。

另外兩個是什麼?在這裏,輸出被解釋爲錯誤的方式。默認情況下,preg_match_all給出了一個二維數組,第一個索引對應於該組,第二個索引對應於該匹配。在你的輸出中,它是相反的解釋。因此,當有多個匹配時,第一對01是兩個找到的匹配的整個匹配。第二對01是你在這兩場比賽中獲得的。

因此對於*,您首先得到完整字符串作爲匹配,並將最後一個字符作爲捕獲(這兩個事物標記爲0),這是正確的。然後,由於*允許零寬度匹配,因此您會在字符串末尾獲得另一個(空)匹配以及空捕獲。我不確定爲什麼相應的JS'示例不包含額外的空字符串,但是,因爲String.match會做同樣的事情。

而對於{4},你只會得到兩場比賽(Trololo!),如JavaScript的情況下與捕獲l!,分別,而這又是完全正常的。

+0

>首先,會發生什麼? 的確如此,這就是問題:-) 我實際上預計,那匹配abcd的(。)*會給0. abcd 1. a 2. b 3. c 4. d - 也就是說,我得到更多的組,因爲量化者似乎量化了這個羣體。但考慮更長時間,這似乎根本無法使用,因爲羣組參考已修復。 – Falko

+1

@Falko,唯一正則表達式就是.NET。在那裏你會得到一個Group對象,每個組包含一組捕捉。 –

+0

啊,很酷。但如前所述,我無法想象這在實踐中可能會有所幫助。 – Falko