2011-11-14 62 views
5

我從一些PHP Textile實現(開源,正確歸因)中借用了一個相當複雜的正則表達式,用於構建一個簡單的,功能不完整的Java實現textile4j,並將其移植到github,同步到Maven中心(最初的代碼是爲blojsom提供的一個插件,這是一個Java博客平臺;這是在Maven Central中提供blojsom依賴關係的一部分)。靠近索引nnn的未封閉字符類

不幸的是,紡織正則表達式的表達式(而他們中的PHP preg_replace_callback環境中工作)失敗,在Java中,以下情況例外:

java.util.regex.PatternSyntaxException: Unclosed character class near index 217

的說法是明顯的,解決的辦法是難以捉摸的。

下面是PHP實現原料,多正則表達式:

return preg_replace_callback('/ 
    (^|(?<=[\s>.\(])|[{[]) # $pre 
    "      # start 
    (' . $this->c . ')  # $atts 
    ([^"]+?)    # $text 
    (?:\(([^)]+?)\)(?="))? # $title 
    ": 
    ('.$this->urlch.'+?) # $url 
    (\/)?     # $slash 
    ([^\w\/;]*?)   # $post 
    ([\]}]|(?=\s|$|\))) 
    /x',callback,input); 

巧妙,我得到了紡織類「告訴我的代碼」,在這個表達式中使用一個簡單的echo,導致以下而長,正則表達式:

(^|(?<=[\s>.\(])|[{[])"((?:(?:\([^)]+\))|(?:\{[^}]+\})|(?:\[[^]]+\])|(?:\<(?!>)|(?<!<)\>|\<\>|\=|[()]+(?!)))*)([^"]+?)(?:\(([^)]+?)\)(?="))?":([\w"$\-_.+!*'(),";\/?:@=&%#{}|\^~\[\]`]+?)(\/)?([^\w\/;]*?)([\]}]|(?=\s|$|\))) 

我已經發現了幾個可能被導致解析錯誤,使用在線工具,如RegExr by gskinnerRegexPlanet可能的領域。但是,這些細節都沒有解決錯誤。

我懷疑有一個範圍問題隱藏在其中一個字符類,或一個Unicode順序隱藏在某處,但我找不到它。

任何想法?我也很好奇爲什麼PHP不會拋出類似的錯誤,例如,我發現一個「被動子表達式」使用RegExr處理得不好,但它沒有修復Java異常,也沒有改變行爲在PHP中,如下所示。

#title切換逃脫括號:

 (?:\(([^)]+?)\)(?="))? # $title 
     ...^ 
     (?:(\([^)]+?)\)(?="))? # $title 
     ....^ 

感謝, 添

編輯:添加以Java String的解釋(與轉義)紡織正則表達式,如RegexPlanet確定...

"(^|(?<=[\\s>.\\(])|[{[])\"((?:(?:\\([^)]+\\))|(?:\\{[^}]+\\})|(?:\\[[^]]+\\])|(?:\\<(?!>)|(?<!<)\\>|\\<\\>|\\=|[()]+(?!)))*)([^\"]+?)(?:\\(([^)]+?)\\)(?=\"))?\":([\\w\"$\\-_.+!*'(),\";\\/?:@=&%#{}|\\^~\\[\\]`]+?)(\\/)?([^\\w\\/;]*?)([\\]}]|(?=\\s|$|\\)))" 
+0

''title'行對我來說看起來不錯。它可以選擇 –

回答

9

@CodeJockey是正確的:有一個在你的字符類的一個方括號需要進行轉義。 []][^]]都還好,因爲]比否定^以外的第一個字符,但在Java中的轉義[在字符類的任意位置是一個語法錯誤。

諷刺的是,原來的正則表達式包含了甚至在PHP需要很多反斜槓。它也逃脫/,因爲這就是它用作正則表達式的分隔符。除草所有這些出來後,我想出了這個Java正則表達式:

"(^|(?<=[\\s>.(])|[{\\[])\"((?:(?:\\([^)]+\\))|(?:\\{[^}]+\\})|(?:\\[[^]]+\\])|(?:<(?!>)|(?<!<)>|<>|=|[()]+(?!)))*)([^\"]+?)(?:\\(([^)]+?)\\)(?=\"))?\":([\\w\"$_.+!*'(),\";/?:@=&%#{}|^~\\[\\]`-]+?)(/)?([^\\w/;]*?)([]}]|(?=\\s|$|\\)))" 

無論是在最好正則表達式,我不知道,不知道它如何被使用。

+0

艾倫,非常感謝調查!基本上,紡織品通過的FARVD成名院長卡梅倫·艾倫在多年前建立一個「鏈接到MediaWiki - 精簡版」文本分析器。語法顯然是非常具有傳染性的,所以我相信但不能確定,TextPattern CMS是圍繞它構建的。所謂的RegEx是用來解析Textile的鏈接語法的。 c.2003是一個紡織的Java端口,Java端口有一個正則表達式無法處理所有的紡織品特徵。看到OP爲我的利益正確。 :) – javafueled

+0

啊,把複雜的正則表達式翻譯成一種不太相容的味道 - 從來沒有一個沉悶的時刻! ;)但是你明白@ FailedDev的答案是錯誤的,是嗎?無論原始正則表達式使用「\ <' or '\>」,它都會嘗試匹配字面尖括號,而不是字邊界。 (我檢查了文檔只是爲了確定;它們是Textile的文本對齊語法的一部分。) –

+0

alan,這確實有效並且更清潔,更少的空白匹配組(從12到9)。紡織是整潔的,但是看代碼,思考TextPattern讓我想起這句話:「有些人在遇到問題時,想」我知道,我會用正則表達式。「現在他們有兩個問題。 - 傑米Zawinski'然後是[傑夫阿特伍德正則表達式了。](http://www.codinghorror.com/blog/2008/06/regular-expressions-now-you-have-two-problems.html) – javafueled

1

我不知道究竟在何處您的問題所在,但是這可能幫助:

在Java中(我相信這是Java獨有的),[符號(不僅僅是]符號)在字符類中保留並且需要轉義。

修訂後的表達也許應該是類似於以下,爲了與Java兼容:

(^|(?<=[\s>.\(])|[{\[]) # $pre 
"      # start 
(' . $this->c . ')  # $atts 
([^"]+?)    # $text 
(?:\(([^)]+?)\)(?="))? # $title 
": 
('.$this->urlch.'+?) # $url 
(\/)?     # $slash 
([^\w\/;]*?)   # $post 
([\]}]|(?=\s|$|\))) 
/x 

基本上,任何地方,最正則表達式的口味將允許字符類像[a-z,;[\]+-] - 這將匹配「以字母a - z或逗號,分號,打開或關閉方括號,加號或減號」,需要實際上是[a-z,;\[\]+-](逃避[\字符)

這逸出REQ要求是由於Java union, intersection and subtraction字符類結構。

+0

匹配括號(拍攝以外的所有括號本身)的東西,但只有當它的收盤'「'之前的最後一件事。事實上,因爲它的Java,你需要用雙**逃吧‘\’**。 – FailedDev

+0

@FailedDev - 是的,任何'\'字符,放入字符串時,就需要進行轉義上面的例子是在PHP中,因此所有的'\'字符,包括'\ S'和'的那些\ ('將需要增加一倍,如果放到一個Java字符串。 –

相關問題