【问题标题】:Unclosed character class near index nnn索引 nnn 附近的未封闭字符类
【发布时间】:2011-12-28 21:45:37
【问题描述】:

我从一些 PHP Textile 实现(开源,正确归因)中借用了一个相当复杂的正则表达式,用于一个简单但功能不完整的 Java 实现,textile4j,我将其移植到 github 并同步到 Maven 中心(编写原始代码是为了为 Java 博客平台 blojsom 提供一个插件;这是在 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 中切换转义的括号:

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

谢谢, 蒂姆

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

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

【问题讨论】:

  • #title 行对我来说看起来不错。它可以选择匹配括号中的内容(捕获除括号本身之外的所有内容),但前提是它是结束 " 之前的最后一件事。

标签: java php regex regexbuddy


【解决方案1】:

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

具有讽刺意味的是,原始的正则表达式包含许多即使在 PHP 中也不需要的反斜杠。它还转义了/,因为它用作正则表达式分隔符。在清除所有这些之后,我想出了这个 Java 正则表达式:

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

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

【讨论】:

  • 艾伦,非常感谢您的调查!基本上,textile 是多年前由 FARVD 的 Dean Cameron Allen 创建的“mediawiki-lite”文本解析器。语法显然具有很强的传染性,所以我相信但不能确定,TextPattern CMS 是围绕它构建的。有问题的 RegEx 取自 PHP,作为 OP,用于解析 Textile 的链接语法。大约在 2003 年的某个时候,一个 Java 端口的 Textile 开始了。 Java 端口有一个无法处理所有纺织特征的正则表达式。请参阅 OP,了解我是否有兴趣正确处理。 :)
  • 啊,将复杂的正则表达式转换为不完全兼容的风格的乐趣——从来没有一个沉闷的时刻! ;) 但你确实明白@FailedDev 的回答是错误的,不是吗?无论原始正则表达式在哪里使用\&lt;\&gt;,它都试图匹配文字尖括号,而不是单词边界。 (为了确定,我检查了文档;它们是 Textile 的文本对齐语法的一部分。)
  • alan,这确实有效,而且更干净,空匹配组更少(从 12 到 9)。 Textile 很整洁,但是看着代码,想想 TextPattern 让我想起了这句话:Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. --Jamie Zawinski 然后是Jeff Atwood on regex too.
  • [愤怒]这个?这就是为什么我收到错误?因为 Java 认为我可以通过一些妖术来在另一个字符类中嵌入一个字符类? [/rage] 好吧,一个能言善辩的人想在 stackoverflow 上解释它是件好事。
  • 呵呵,这也发生在我身上 - 我想检查输入中的反斜杠,但我忘了双转义它们(第一次是 Java 字符串,第二次是正则表达式,我必须写成"\\\\")
【解决方案2】:

我不确定您的问题到底出在哪里,但这可能会有所帮助:

在 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 字符类结构造成的。

【讨论】:

  • 其实因为它是 java 你需要用双 '\' 来转义它。
  • @FailedDev - 是的,任何\ 字符在放入字符串时都需要转义。上面的例子是用 PHP 编写的,所以所有的 \ 字符,包括 \s \( 中的字符,如果放入 Java 字符串中,都需要加倍。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
相关资源
最近更新 更多