我从一些 PHP Textile 实现(开源,适当归因)中借用了一个相当复杂的正则表达式,用于一个简单但功能不完全的 Java 实现,textile4j,我将其移植到 github 并同步到 Maven 中心(原始代码是为 Java 博客平台 blojsom 提供一个插件;这是在 Maven Central 中提供 blojsom 依赖项的更大努力的一部分)。
不幸的是,纺织正则表达式(虽然它们preg_replace_callback
在 PHP 的上下文中工作)在 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|$|\)))
我使用在线工具(例如gskinner 的 RegExr和RegexPlanet)发现了几个可能导致解析错误的区域。但是,这些细节都不能解决该错误。
我怀疑其中一个字符类中隐藏了一个范围问题,或者隐藏在某个地方的 Unicode 顺序,但我找不到它。
有任何想法吗?
我也很好奇为什么 PHP 不会抛出类似的错误,例如,我发现一个“被动子表达式”使用 RegExr 处理得不好,但它没有修复 Java 异常,也没有改变 PHP 中的行为,如图所示以下。
在#title
切换转义的括号中:
(?:\(([^)]+?)\)(?="))? # $title
...^
(?:(\([^)]+?)\)(?="))? # $title
....^
谢谢,蒂姆
编辑:添加由RegexPlanet确定的 Textile 正则表达式的 Java 字符串解释(带有转义)...
"(^|(?<=[\\s>.\\(])|[{[])\"((?:(?:\\([^)]+\\))|(?:\\{[^}]+\\})|(?:\\[[^]]+\\])|(?:\\<(?!>)|(?<!<)\\>|\\<\\>|\\=|[()]+(?! )))*)([^\"]+?)(?:\\(([^)]+?)\\)(?=\"))?\":([\\w\"$\\-_.+!*'(),\";\\/?:@=&%#{}|\\^~\\[\\]`]+?)(\\/)?([^\\w\\/;]*?)([\\]}]|(?=\\s|$|\\)))"