Я заимствую довольно сложное регулярное выражение из некоторых реализаций PHP Textile (с открытым исходным кодом, с правильной атрибуцией) для простой, не совсем полнофункциональной реализации Java, Textile4j, которая Я портирую на github и синхронизируюсь с Maven central (исходный код был написан для предоставления плагина для blojsom, платформы для ведения блогов на Java; это часть более масштабных усилий по обеспечению доступности зависимостей blojsom в Maven Central).
К сожалению, выражения текстильных регулярных выражений (хотя они работают в контексте preg_replace_callback
в PHP) не работают в Java за следующим исключением:
java.util.regex.PatternSyntaxException: Незакрытый символьный класс рядом с индексом 217
Утверждение очевидно, решение неуловимо.
Вот необработанное многострочное регулярное выражение из реализации PHP:
return preg_replace_callback('/
(^|(?<=[\s>.\(])|[{[]) # $pre
" # start
(' . $this->c . ') # $atts
([^"]+?) # $text
(?:\(([^)]+?)\)(?="))? # $title
":
('.$this->urlch.'+?) # $url
(\/)? # $slash
([^\w\/;]*?) # $post
([\]}]|(?=\s|$|\)))
/x',callback,input);
Я ловко заставил класс Textile «показать мне код», используемый в этом регулярном выражении, с помощью простого echo
, что привело к следующее, довольно длинное, регулярное выражение:
(^|(?<=[\s>.\(])|[{[])"((?:(?:\([^)]+\))|(?:\{[^}]+\})|(?:\[[^]]+\])|(?:\<(?!>)|(?|\<\>|\=|[()]+(?! )))*)([^"]+?)(?:\(([^)]+?)\)(?="))?":([\w"$\-_.+!*'(),";\/?:@=&%#{}|\^~\[\]`]+?)(\/)?([^\w\/;]*?)([\]}]|(?=\s|$|\)))
Я обнаружил несколько возможных областей, которые могут приводить к ошибкам синтаксического анализа, используя онлайн-инструменты, такие как RegExr от gskinner и RegexPlanet . Однако ни одна из этих подробностей не устраняет ошибку.
Я подозреваю , что в одном из классов символов скрыта проблема диапазона или где-то прячется порядок Unicode, но я не могу ее найти.
Есть идеи?
Мне также любопытно, почему PHP не выдает аналогичную ошибку, например, я обнаружил, что одно «пассивное подвыражение» плохо обрабатывается с помощью RegExr, но оно не исправляет исключение Java и не изменил поведение PHP, показанное ниже.
В #title
переключите экранированный парен:
(?:\(([^)]+?)\)(?="))? # $title
...^
(?:(\([^)]+?)\)(?="))? # $title
....^
Спасибо, Тим
отредактируйте: добавление интерпретации Java String (с экранированием) текстового регулярного выражения, как определено RegexPlanet ...
"(^|(?<=[\\s>.\\(])|[{[])\"((?:(?:\\([^)]+\\))|(?:\\{[^}]+\\})|(?:\\[[^]]+\\])|(?:\\<(?!>)|(?|\\<\\>|\\=|[()]+(?! )))*)([^\"]+?)(?:\\(([^)]+?)\\)(?=\"))?\":([\\w\"$\\-_.+!*'(),\";\\/?:@=&%#{}|\\^~\\[\\]`]+?)(\\/)?([^\\w\\/;]*?)([\\]}]|(?=\\s|$|\\)))"