【发布时间】: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 gskinner 和RegexPlanet 等在线工具发现了几个可能导致解析错误的区域。但是,这些细节都不能解决错误。
我怀疑其中一个字符类中隐藏了一个范围问题,或者隐藏在某处的 Unicode 顺序,但我找不到它。
有什么想法吗?
我也很好奇为什么 PHP 没有抛出类似的错误,例如,我发现一个“被动子表达式”使用 RegExr 处理不当,但它没有修复 Java 异常,也没有改变PHP,如下所示。
在#title 中切换转义的括号:
(?:\(([^)]+?)\)(?="))? # $title
...^
(?:(\([^)]+?)\)(?="))? # $title
....^
谢谢, 蒂姆
编辑:添加 Textile 正则表达式的 Java 字符串解释(带有转义),由 RegexPlanet 确定...
"(^|(?<=[\\s>.\\(])|[{[])\"((?:(?:\\([^)]+\\))|(?:\\{[^}]+\\})|(?:\\[[^]]+\\])|(?:\\<(?!>)|(?<!<)\\>|\\<\\>|\\=|[()]+(?! )))*)([^\"]+?)(?:\\(([^)]+?)\\)(?=\"))?\":([\\w\"$\\-_.+!*'(),\";\\/?:@=&%#{}|\\^~\\[\\]`]+?)(\\/)?([^\\w\\/;]*?)([\\]}]|(?=\\s|$|\\)))"
【问题讨论】:
-
#title行对我来说看起来不错。它可以选择匹配括号中的内容(捕获除括号本身之外的所有内容),但前提是它是结束"之前的最后一件事。
标签: java php regex regexbuddy