2016-05-05 5 views
2

この質問はJava 7/8に固有です。数量を使用していますルックバックヒント式の中で量子を使用できますか?

Aかなり複雑な正規表現は、このいずれかのように戻り読み言明内で禁止されています:

(?<=(a|b*)*)bc 

それはのようなメッセージが表示され、実行時例外が発生して:私は推測してい

look-behind group does not have obvious maximum length error 

*+のような量指定子は「一般的に」許可されていないためです。

ただし、次の作業を行います。

(?<=a*)bc 

なぜこれがそうですか?

SO上でこの問題について同様の記事があります。その他の言語については

  1. rubyPCRE etc-

  2. はいくつかの記事では、Javaに固有のものですが、コンクリートを提供していないようです回答または参考文献(thisなど)ほとんどの場合、これらの量指定子は単純に使用できないと答えています。また、regular-expressionsのウェブサイトも同じです。

  3. This post状態Javaには実装上のバグがあります。

しかし、私はその上に示された例では、後読みの内部ゼロまたは多数の数量詞*を使用するJava 7/8に有効です。

参考文献や説明が参考になります。

+1

(注:これはJLSではなくライブラリのドキュメントで指定されています) –

+0

[ライブラリのドキュメント](http://docs.oracle.com/javase/8/docs/api/java/util/regex /Pattern.html)は実際にそれを指定しません。特定の動作を記述したO'Reillyの本を紹介しています。 – ajb

+0

ありがとうございます。私は訂正をしました。 –

答えて

1

Patternコードを見て、それをトレースしようとすると、これは単なるバグであると確信しています。どちらの例でも例外が発生するはずです。しかし、これをテストするロジックは間違っています。

このコードは、カップルの場所に表示されます。オーバーフローが発生した場合を除き限りmaxLengthcmaxが非負ある

temp = info.maxLength * cmax + maxL; 
info.maxLength = temp; 
if (temp < maxL) { 
    info.maxValid = false; 
} 

注意、temp未満maxLてはいけません。最終的にlookbehindコードでmaxValidが使用されます。 maxValidfalseの場合、"look-behind group does not have obvious maximum length error"がスローされます。

私はinfo.maxLengthは、cmaxは数量詞の上限である、「表現」の最大の長さである、上記のコードでは、<プレフィックス><式>{m,n}のような正規表現では、伝えることができるものから、 maxLは「接頭辞」の最大長です。量指定子が*または+の場合、上限はInteger.MAX_VALUEに設定されます。(ここでの変数はすべてintです。)これは、info.maxLengthが1で、maxLが0でない限り、オーバーフローがになることを意味します。数量詞とのパターンは長さ1を有し、かつmaxLはこのケースが割れて落ちる理由は0だということを意味しますa*の前に何もないので、それはまさに

(?<=a*)bc 

の場合です。

他の値の場合、計算はオーバーフローしますが、必ずしもtemp < maxLが真となることを意味しません。 info.maxLengthが偶数の場合、例外がスローされます。 info.maxLengthが奇数の場合、maxLが十分小さい場合、パターンはコンパイルされます。これは、数学的にラップアラウンドの仕組みのためです。オーバーフローをチェックしようとするコードはかなり不具合です。

(?<=xa*)bc  // throws exception 
(?<=x(abc)*)bc // succeeds 

注:あなたの例の正規表現では、後読みは無用であることに留意すべきである:

(?<=a*)bc 

後読みをするかどうかをテストするために言って、これはまた、その

(?<=a*)bc   // succeeds 
(?<=(ab)*)bc  // throws exception 
(?<=(abc)*)bc  // succeeds 
(?<=(abcd)*)bc // throws exception 
(?<=(abcde)*)bc // succeeds 

を意味し、現在の場所の前には、0文字以上の文字が現れます。a。これはいつも真実です。そのため、lookbehindはここで目的を果たしません。限り、現在の位置の前の1 aがありますように、あるかもしれませんどのように多くのより多くの問題ではありませんので、同様に、

(?<=a+)bc 

(?<=a)bc 

に相当します。マッチャが後方の文字列でabc年代を探していると、必ず最後作りに行かなければならないので、ここで

(?<=x(abc)*)bc // succeeds 

:同じことは、この1を除いて、例外をスローしていないすべての例でも同様です1つはxです。この場合、Patternは例外をスローするはずですが、オーバーフローチェックロジックが誤っているため、そうではありません。したがって、実際に正しい結果が返されるか、クラッシュするか無限ループになるかは不明です。しかし、私はそれを試していない。

cmaxInteger.MAX_VALUEに等しいかどうかを直接チェックするだけでなく、コードが後でその結果が偽であることを伝えることができることを期待してください。

関連する問題