2012-04-07 40 views
2

我對基本的reg-ex很滿意。但是這條用於大量分離的代碼超出了我的知識範圍,並且使用它進行了相當多的搜索也沒有滿足我的好奇心。可以請你花一分鐘向我解釋下面的代碼行嗎?這個正則表達式超出了我的理解「(?=(?: d {3})++(?! d))」

someString.replaceAll("(\\G-?\\d{1,3})(?=(?:\\d{3})++(?!\\d))", "$1,"); 

我特別不理解正則表達式結構"(?=(?:\d{3})++(?!\d))"

感謝很多提前。

回答

3

"(?=(?:\d{3})++(?!\d))"lookahead assertion。 「

這意味着」只有後跟((我們不需要捕獲的三位數字)重複一次或多次(並且再次重複一次或多次)(後面跟着一個數字)才匹配)「 。請參閱explanation(?:...)表示法。它被稱爲非捕獲組,意味着在比賽結束後你不需要參考這個組。

"(\\G-?\\d{1,3})"是應該實際匹配的部分(但只有滿足上述條件時)。

編輯:我認爲+必須是特殊字符,否則它只是一個加號。如果它是一個特殊字符(快速搜索暗示it is in Java, too),則第二個是多餘的。

編輯2:感謝Alan Moore,現在很清楚。第二個+意味着所有格匹配,所以這意味着如果在檢查了儘可能多的3位數組後,它不會發現它們後面沒有非數字,那麼引擎將立即放棄而不是步進一個3數組返回。

+2

不,第二個'+'不是多餘的;它使第一個「+」[所有格](http://www.regular-expressions.info/possessive.html)。 – 2012-04-07 16:27:23

+0

非常感謝 - 幫助! – dotwin 2012-04-07 16:38:40

+0

對「++」和「+」進行試驗並不會對結果產生任何影響,無論我把整數放在我的整數後面(在java中)。所以我想這實際上只是一個表現問題。 – dotwin 2012-04-07 17:04:15

3

這個表達式有一些先進的東西在裏面。首先,最簡單的方法是:\d{3}意味着三位數字。這些是你的數千人。

那麼:++是+(它意味着一個或多個)的變體,但佔有慾,這意味着它將吃掉所有的數千個。我不完全確定爲什麼這是必要的。

?:意味着它是一個非捕獲組 - 我認爲這只是出於性能原因,可以省略。

?=是一個積極的預測 - 我認爲這意味着它只檢查該組是否存在,但不會計入匹配的字符串 - 這意味着它不會被替換。

?!是負前瞻 - 我不太明白這一點,但我認爲,這意味着它必須比賽,這反過來又意味着不能在匹配序列結束另一個數字。這可以確保第一組獲得正確的數字。例如。如果你明白我的意思,10000只能匹配爲10(000)而不是1(000)0。

通過預見,如果我理解正確(我還沒有測試過),只有第一組實際會被替換,因爲它是匹配的。

+0

非常感謝...! – dotwin 2012-04-07 16:40:03

+0

所有格++不是必須的。它使得正則表達式稍微更有效率(正如@Lev所觀察的那樣),但我懷疑你會注意到這種差異。是什麼讓**正確**是'(?!\ d)'。正則表達式*將匹配多個數字組;在'12345678'中,例如,它將首先匹配'12',然後匹配'345'。 – 2012-04-07 19:56:56

2

對我而言,該正則表達式中最有趣的部分是\G。我花了一段時間來記住它的用途:防止在小數部分添加逗號(如果有的話)。如果正則表達式是簡單的:

(-?\d{1,3})(?=(?:\d{3})++(?!\d)) 

...這個數字:

12345.67890 

......竟又是:

12,345.67,890 

但添加\G到開始指匹配只能從字符串的開頭或前一場比賽結束的位置開始。所以它不匹配345,因爲它後面有.,並且它不匹配67,因爲它必須跳過某些字符串才能這樣做。所以它正確地返回:

12,345.67890 

我知道這不是問題的答案,但我認爲這是值得一提的。

相關問題