索引nnn附近的未闭合字符类

时间:2011-11-14 18:32:32

标签: java php regex regexbuddy

我正在从一些PHP Textile实现(开源,正确归因)中借用一个相当复杂的正则表达式,用于一个简单的,不完全特征的完整Java实现,textile4j,我正在移植到github并同步到Maven central(编写原始代码是为了为blojsom提供一个插件,这是一个Java博客平台;这是在Maven Central中提供blojsom依赖项的更大努力的一部分。)

不幸的是,纺织品正则表达式(当它们在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切换转义的paren:

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

谢谢, 添

编辑:添加Tex正则表达式的Java字符串解释(带转义),由RegexPlanet确定...

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

2 个答案:

答案 0 :(得分:9)

@CodeJockey是正确的:你的一个角色类中有一个方括号需要转义。 []][^]]是可以的,因为]是除否定^之外的第一个字符,但在Java中,字符类中任何位置的未转义[都是语法错误。

具有讽刺意味的是,原始正则表达式包含许多反斜杠,即使在PHP中也是如此。它也会逃脱/,因为它用作正则表达式分隔符。除草了所有这些后,我想出了这个Java正则表达式:

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

是否是最佳正则表达式我不知道,不知道它是如何使用的。

答案 1 :(得分: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,;\[\]+-](以[字符转义\

这个转义要求是由于Java union, intersection and subtraction字符类构造。