6

今日、私は次の正規表現に出くわし、Ruby がそれで何をするか知りたいと思いました:

> "#a" =~ /^[\W].*+$/
=> 0
> "1a" =~ /^[\W].*+$/
=> nil

この例では、Ruby は+文字を無視しているようです。それが正しくない場合、それで何をしているのかわかりません。*はエスケープされておらず、量指定子として使用されているため、量指定子として解釈されていないと思います。Perl/Ruby の正規表現で-は、特殊文字として解釈できないコンテキストで文字 (たとえば、) が使用されると、リテラルとして扱われることがあります。しかし、この場合、+左辺値文字列に no がないため、最初の一致が失敗することが予想されます。

これは微妙に正しい+キャラクターの使い方ですか?上記の動作はバグですか?明らかな何かが欠けていますか?

4

1 に答える 1

5

確かに a の+後に a を使用できます*このサイトで少し読むことができます。の+後ろ*は、所有量指定子と呼ばれます。

それは何をしますか?*バックトラックを防ぎます。

通常、 のようなものが.*cあり、これを使用して に一致させるabcde場合、.*は最初に文字列全体 ( ) に一致し、 の後にabcde正規表現を一致させることはできないため、エンジンは一度に 1 文字戻って一致があるかどうかを確認します (このバックトラッキングです)。c.*

にバックトラックすると、からc一致が得られます。abcabcde

ここで、エンジンが数百文字をバックトラックする必要があると想像してください。ネストされたグループと複数の*(または+フォーム{m,n}) がある場合、数千、数百万の文字をバックトラックすることになり、壊滅的なバックトラックと呼ばれます。

ここで所有量指定子が役に立ちます。それらは実際にあらゆる形態のバックトラッキングを防ぎます。上記の正規表現では、abcdeとは一致しません.*+c。文字列全体を消費すると.*+、バックトラックできずc、文字列の最後に no がないため、一致は失敗します。

したがって、所有量指定子の別の使用方法として、エンジンがサポートできる場合、一部の正規表現のパフォーマンスを向上させることができます。

あなたの regex について/^[\W].*+$/は、所有量指定子が提供する改善(おそらくほんの少しの改善)があるとは思いません。最後に、次のように簡単に書き換えることができます/^\W.*+$/

于 2013-09-24T04:24:09.830 に答える