1

私は昨年からこの質問を見ていました: Java Regex での長さゼロの一致:

Pattern pattern = Pattern.compile("a?");
Matcher matcher = pattern.matcher("ababa");
while(matcher.find()){
   System.out.println(matcher.start()+"["+matcher.group()+"]"+matcher.end());
}

出力を生成します:

0[a]1
1[]1
2[a]3
3[]3
4[a]5
5[]5

これが正しいかどうか疑問に思っています。パターンは、「a」または空の文字列のいずれかに一致します。Matcher が最初の「b」を指している場合、「a」がないため、find() は空の文字列に一致します。

ただし、javadocには次のように記載されています。

このメソッドは、このマッチャーの領域の先頭から開始します。または、メソッドの以前の呼び出しが成功し、その後マッチャーがリセットされていない場合は、以前の一致で一致しなかった最初の文字から開始します。

そのため、Matcher が 'b' を指している場合、一致する文字はなく、find() は空の文字列と一致します。つまり、その後、前の一致で一致しなかった最初の文字 (つまり空の文字列) は引き続き 'b になります。 '。これは、上記に従って、次の find() が同じ場所で開始する必要があることを意味する必要があります。これは、コードが無限にループする必要があることを意味します。しかしもちろん、それは起こっていることではありません。空の文字列が一致すると、開始点が 1 つ上がるだけのようです。

元気?実装が間違っているのでしょうか、それとも javadoc で何かが省略されているのでしょうか?

4

2 に答える 2

1

OK、find() が空の文字列を返す特殊なケースがあるようです。明確にするために、質問を理解していない人もいると思うので、私の問題は、「最初の文字が前のmatch」はどちらの場合も同じになります。

違いは、前の一致の境界がマッチャーの状態に保存され、次の find() に影響を与えることですが、この 1 つの場合のみです。Matcher.java の find() コードから:

 int nextSearchIndex = last;
 if (nextSearchIndex == first)
      nextSearchIndex++;

lastfirst最後の find() が空の文字列を返した (またはlast他のメソッドによって設定された) 場合を除き、検索が開始される場所であり、その後 1 つ上に移動します。このスニペットにはコメントがないので、目的はわかりませんが、意図的に空の文字列の一致という特殊なケースを作成しているようです。ただし、これは javadoc と矛盾しているように見えます。これは、この 1 つのケースでは、javadoc に記載されている場所とは異なる場所で検索が開始されるためです。

EDIT:ちなみに、これは驚くべき結果をもたらします:

 Pattern p = Pattern.compile("a?");
 Matcher m = p.matcher ("abcde");
 m.find();
 System.out.println("[" + m.group() + "]");
 m.find();
 System.out.println("[" + m.group() + "]");
 m.usePattern (Pattern.compile("[bd]"));
 m.find();
 System.out.println("[" + m.group() + "]");

出力

[a]
[]
[d]

「b」文字は以前の一致で一致しておらず、スキップされるべきではありませんでしたが、最後の一致では「b」が見つかりません。ちょっとわかりにくいですけどね。

于 2013-07-30T18:07:40.440 に答える