0

ここからregexを使用して、文字列内のURLを照合しようとしています:JavaでURLを照合するための正規表現

1つのURLで正常に機能しますが、文字列に2つのURLがある場合、後者にしか一致しませんでした。

コードは次のとおりです。

Pattern pat = Pattern.compile(".*((https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])", Pattern.DOTALL);
Matcher matcher = pat.matcher("asdasd http://www.asd.as/asd/123 or http://qwe.qw/qwe");
// now matcher.groupCount() == 2, not 4

編集:私が試したもの:

// .* removed, now doesn't match anything // Another edit: actually works, see below
Pattern pat = Pattern.compile("((https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])", Pattern.DOTALL);

// .* made lazy, still only matches one
Pattern pat = Pattern.compile(".*?((https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])", Pattern.DOTALL);

何か案は?

4

1 に答える 1

5

.*貪欲だからです。できるだけ多く(文字列全体)を消費してからバックトラックします。つまり、残りの文字がURLを構成できるようになるまで、一度に1文字ずつ破棄されます。したがって、最初のURLはすでに一致していますが、キャプチャされていません。残念ながら、一致は重複できません。修正は簡単なはずです。.*パターンの先頭にあるを削除します。次に、パターンから外側の括弧を削除することもできます。一致するもの全体が探しているURLになるため、これ以上何もキャプチャする必要はありません。

Pattern pat = Pattern.compile("(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]", Pattern.DOTALL);
Matcher matcher = pat.matcher("asdasd http://www.asd.as/asd/123 or http://qwe.qw/qwe");
while (matcher.find()) {
  System.out.println(matcher.group());
}

ちなみに、matcher.groupCount()それはあなたのパターンのグループの数をあなたに与え、あなたのターゲット文字列のキャプチャの数をあなたに与えないので、あなたに何も教えません。そのため、2番目のアプローチ(を使用.*?)は役に立ちませんでした。パターンにはまだ2つのキャプチャグループがあります。電話をかける前findなどmatcher、合計でいくつのキャプチャが見つかるかわかりません。

于 2012-12-06T23:08:01.253 に答える