32

Atomic Groupingruby​​infoのドキュメントを調べたところ、いくつかの質問が頭に浮かびました。

  1. なぜ「アトミックグルーピング」という名前なのですか? 一般的なグループ化にはない「原子性」は何ですか?
  2. アトミック グループ化は、一般的なグループ化とどのように異なりますか?
  3. 原子団が非捕獲群と呼ばれるのはなぜですか?

理解するために以下のコードを試しましたが、出力について混乱し、同じ文字列でもどのように機能するかが異なりましたか?

irb(main):001:0> /a(?>bc|b)c/ =~ "abbcdabcc"
=> 5
irb(main):004:0> $~
=> #<MatchData "abcc">
irb(main):005:0> /a(bc|b)c/ =~ "abcdabcc"
=> 0
irb(main):006:0> $~
=> #<MatchData "abc" 1:"b">
4

3 に答える 3

58

A()にはいくつかのプロパティ(、、(?!pattern)など(?=pattern)とプレーンを(pattern)含む)がありますが、それらすべてに共通するプロパティはグループ化です。これにより、任意のパターンが単一のユニットになります(ユニットは私自身の用語です)。これは繰り返しに役立ちます。 。

通常のキャプチャには、キャプチャグループ(pattern)化のプロパティがあります。キャプチャとは、テキストが内部のパターンと一致することを意味し、一致または置換で、後方参照で使用できるようにキャプチャされます。非キャプチャグループにはキャプチャプロパティがないため、パターンに一致する文字列の開始インデックスと終了インデックスが内部に格納されないため、スペースが少し節約され、速度が少し向上します。(?:pattern)(pattern)

アトミックグループ化(?>pattern)には非キャプチャプロパティもあるため、内部で一致したテキストの位置はキャプチャされません。

アトミックグループ化は、キャプチャまたは非キャプチャグループと比較してアトミックのプロパティを追加します。ここでのアトミックとは、現在の位置で、アトミックグループ内のパターンに一致する最初のシーケンス(最初は、指定されたパターンに従ってエンジンがどのように一致するかによって定義されます)を見つけ、それを保持することを意味します(バックトラックは許可されません)。

アトミック性のないグループはバックトラックを許可します-それでも最初のシーケンスを見つけ、先の一致が失敗した場合、正規表現全体の一致が見つかるか、すべての可能性が尽きるまで、バックトラックして次のシーケンスを見つけます。

入力文字列:bbabbbabbbbc
パターン:/(?>.*)c/

による最初の一致.*bbabbbabbbbc、貪欲な数量詞によるもの*です。それはこの試合を保持し、試合を禁止cします。マッチャーは文字列の最後の次の位置で再試行し、同じことが起こります。したがって、正規表現に一致するものはまったくありません。


入力文字列:bbabbbabbbbc
パターン:/((?>.*)|b*)[ac]/、テスト用/(((?>.*))|(b*))[ac]/

この正規表現には、、、、の3つの一致がbbaありbbbaますbbbbc。2番目の正規表現を使用する場合、これは同じですが、デバッグ目的でキャプチャグループが追加されているため、すべての一致がb*内部の一致の結果であることがわかります。

ここでバックトラッキングの動作を確認できます。

  • アトミックグループ化がない/(.*|b*)[ac]/と、一致する最後のバックトラックにより、文字列は文字列全体である単一の一致になり[ac]ます。.*他の可能性があるため、エンジンは1文字ずつバックトラックに戻ることに注意してください。

    Pattern: /(.*|b*)[ac]/
    bbabbbabbbbc
    ^             -- Start matching. Look at first item in alternation: .*
    bbabbbabbbbc
                ^ -- First match of .*, due to greedy quantifier
    bbabbbabbbbc
                X -- [ac] cannot match
                  -- Backtrack to ()      
    bbabbbabbbbc
               ^  -- Continue explore other possibility with .*
                  -- Step back 1 character
    bbabbbabbbbc
                ^ -- [ac] matches, end of regex, a match is found
    
  • アトミックグループ化では、のすべての可能性.*が遮断され、最初の一致に制限されます。したがって、文字列全体を貪欲に食べて一致しなかった後、エンジンはb*パターンを選択する必要があり、正規表現との一致が正常に検出されます。

    Pattern: /((?>.*)|b*)[ac]/
    bbabbbabbbbc
    ^             -- Start matching. Look at first item in alternation: (?>.*)
    bbabbbabbbbc
                ^ -- First match of .*, due to greedy quantifier
                  -- The atomic grouping will disallow .* to be backtracked and rematched
    bbabbbabbbbc
                X -- [ac] cannot match
                  -- Backtrack to ()
                  -- (?>.*) is atomic, check the next possibility by alternation: b*
    bbabbbabbbbc
    ^             -- Starting to rematch with b*
    bbabbbabbbbc
      ^           -- First match with b*, due to greedy quantifier
    bbabbbabbbbc
       ^          -- [ac] matches, end of regex, a match is found
    

    その後の試合はここから続きます。

于 2013-01-19T07:48:31.587 に答える
4

「アトミックグループ」とは、正規表現が過去にさかのぼることがないグループです。したがって、最初の例では、グループ内/a(?>bc|b)c/の交代が一致した場合bc、それからバックトラックしてb交代を試みることはありません。最初の例を少し変更して一致させると、文字列の先頭ではなく末尾のに"abcdabcc"一致することがわかります。アトミックグループを使用しない場合は、アトミックグループをバックトラックして交互に試行し、最初にアトミックグループと一致する可能性があります。"abcc""abc"bcb"abc"

質問2については、それがどのように違うのか、それはあなたの最初の質問の言い換えにすぎません。

そして最後に、アトミックグループは「非キャプチャグループと呼ばれる」ものではありません。それは彼らの別名ではありません。非キャプチャグループは、コンテンツをキャプチャしないグループです。通常、正規表現を文字列と照合すると、一致したすべてのグループを取得できます。置換を使用する場合は\1、キャプチャされたグループをそこに挿入するように、置換で後方参照を使用できます。しかし、非キャプチャグループはこれを提供しません。古典的な非キャプチャグループは(?:pattern)です。アトミックグループには、たまたま非キャプチャプロパティもあるため、非キャプチャグループと呼ばれるのはなぜですか。

于 2013-01-19T07:34:18.453 に答える