5

いくつかのPHPテキスタイル実装(オープンソース、適切に属性付けされている)からかなり複雑な正規表現を借りて、完全なJava実装であるtextile4jをgithubに移植し、Mavenセントラルに同期しています(元のコードはJavaブログプラットフォームであるblojsomのプラグインを提供するために作成されました。これは、blojsomの依存関係をMaven Centralで利用できるようにするためのより大きな取り組みの一部です)。

残念ながら、テキスタイル正規表現は(preg_replace_callbackPHPのコンテキストで機能しますが)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などのオンラインツールを使用して、解析エラーが発生する可能性のあるいくつかの領域を明らかにしました。ただし、これらの詳細のいずれもエラーを修正しません。

文字クラスの1つに範囲の問題が隠されているか、Unicodeの順序がどこかに隠れているのではないかと思いますが、見つかりません。

何か案は?

また、PHPが同様のエラーをスローしない理由にも興味があります。たとえば、1つの「パッシブ部分式」がRegExrを使用して適切に処理されていないことがわかりましたが、Java例外が修正されず、PHPの動作が変更されませんでした。下。

#titleエスケープされたパレンを切り替えます。

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

ありがとう、ティム

編集: RegexPlanetによって決定されたテキスタイル正規表現のJava文字列解釈(エスケープ付き)を追加します...

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

2 に答える 2

9

@CodeJockey は正しいです。エスケープする必要がある文字クラスの 1 つに角かっこがあります。 []]またはは、否定する 以外の最初の文字である[^]]ため問題ありませんが、Java では、文字クラス内 のエスケープされていない a は構文エラーです。]^[

皮肉なことに、元の正規表現には、PHP でも不要なバックスラッシュが多数含まれています。また/、それが正規表現区切り文字として使用されるため、エスケープします。それらをすべて取り除いた後、私はこの Java 正規表現を思いつきました:

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

それがどのように使用されているのかわからないため、それが最高の正規表現であるかどうかはわかりません。

于 2011-11-15T09:00:33.323 に答える
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の和集合、共通部分、および減算の文字クラス構造によるものです。

于 2011-11-14T18:49:18.033 に答える