8

最近の質問で述べたように、問題を再現するには - (.*)* が 2 つの一致を作成し、グループ $1 で何も選択しないのはなぜですか? *+、括弧の内側と外側のさまざまな組み合わせを試してみましたが、得られた結果は期待どおりではありませんでした。

その質問の受け入れられた回答で説明されているものと同じ出力を期待していたPerlでしょう。. しかし、同じように振る舞うわけではありません。

簡単にするために、私が試したコードは次のとおりです。

String str = "input";
String[] patterns = { "(.*)*", "(.*)+", "(.+)*", "(.+)+" };

for (String pattern: patterns) {
    Matcher matcher = Pattern.compile(pattern).matcher(str);

    while (matcher.find()) {
        System.out.print("'" + matcher.group(1) + "' : '" + matcher.start() + "'" + "\t");
    }

    System.out.println();
}

そして、これは私が4つの組み合わせすべてに対して得た出力です: -

'' : '0'    '' : '5'            // For `(.*)*`
'' : '0'    '' : '5'            // For `(.*)+`  
'input' : '0'   'null' : '5'    // For `(.+)*`
'input' : '0'                   // For `(.+)+`

さて、私が理解できないのは、なぜ in1st2ndoutput で、 のように文字列全体を取得していないのかということfirst resultですmatcher.find()。つまり、理想的には、最初のケースで.*は、最初に文字列全体をキャプチャしてから、最後に もキャプチャする必要がありempty stringます。現在、第 2 試合では期待どおりの結果が得られていますが、 ではうまく動作していません1st match

+また、2 番目のケースでは、ブラケットの外側に量指定子があるため、2 番目の一致を取得することさえできません。

私の予想される出力は次のとおりです。

'input' : '0'   '' : '5'  // For 1st
'input' : '0'    // For 2nd

また、3rd出力で、なぜnull代わりに 2 番目の一致が得られたのempty stringですか? 最初の 3 つの組み合わせの 2 番目の一致は同じであるべきではありませんか?

4番目の出力は予想どおりです。ですから、間違いありません。

4

1 に答える 1

7

リンクした質問で見たのと同じ現象の影響が見られます。

の場合(.*)*

  • 1つ目matcher.start()0、そこから一致("input")が始まるためです。
  • 1つ目matcher.group(1)""、repeated(.*)がキャプチャさ"input"れた文字列を空の文字列で上書きしたためです(ただし、matcher.group(0)が含まれていますinput")。
  • 2つ目matcher.start()5、最初の一致が成功した後、正規表現エンジンが存在するためです。
  • 2番目matcher.group(1)(およびmatcher.group(0))は""、文字列の最後で一致する必要があるのはそれだけだからです。

それ(.*)+は同じだからです。結局のところ、空の文字列は何度でも繰り返すことができ、それでも空の文字列のままです。

(.+)*2番目の一致が成功してnullいる間(長さ1の文字列のゼロの繰り返しが空の文字列と一致する)、キャプチャ括弧は何もキャプチャできなかったため、その内容は(nullundefinedのように、空の文字列ではなく) )。

于 2013-01-24T12:04:24.427 に答える