web-dev-qa-db-ja.com

Java regex:負の先読み

URIに一致する2つの正規表現を作成しようとしています。これらのURIは次の形式です:_/foo/someVariableData_および_/foo/someVariableData/bar/someOtherVariableData_

2つの正規表現が必要です。それぞれが一方に一致する必要がありますが、他方には一致しない必要があります。

最初に思いついた正規表現は、それぞれ_/foo/.+_と_/foo/.+/bar/.+_です。

2番目の正規表現は問題ないと思います。 2番目の文字列にのみ一致します。ただし、最初の正規表現は両方に一致します。それで、ネガティブな先読みで(初めて)遊んでみました。正規表現/foo/.+(?!bar)を設計し、次のコードを設定してテストします

_public static void main(String[] args) {
    String shouldWork = "/foo/abc123doremi";
    String shouldntWork = "/foo/abc123doremi/bar/def456fasola";
    String regex = "/foo/.+(?!bar)";
    System.out.println("ShouldWork: " + shouldWork.matches(regex));
    System.out.println("ShouldntWork: " + shouldntWork.matches(regex));
}
_

そして、もちろん、両方ともtrueに解決されます。

誰かが私が間違っていることを知っていますか?必ずしもネガティブ先読みを使用する必要はありません。問題を解決する必要があります。ネガティブ先読みはそれを行う1つの方法であると思います。

ありがとう、

34
Cody S

試して

String regex = "/foo/(?!.*bar).+";

または多分

String regex = "/foo/(?!.*\\bbar\\b).+";

/foo/baz/crowbarsのようなパスでの失敗を避けるために、その正規表現を一致させたいと思います。

説明:(Java文字列)で必要な二重のバックスラッシュなし)

/foo/ # Match "/foo/"
(?!   # Assert that it's impossible to match the following regex here:
 .*   #   any number of characters
 \b   #   followed by a Word boundary
 bar  #   followed by "bar"
 \b   #   followed by a Word boundary.
)     # End of lookahead assertion
.+    # Match one or more characters

「単語境界アンカー」\bは、英数字と非英数字の間(または文字列の開始/終了とalnum文字の間)の空のスペースに一致します。したがって、"bar"bの前またはrの後に一致しますが、"crowbar"wbの間の一致は失敗します。

ヒント: http://www.regular-expressions.info -素晴らしい正規表現チュートリアルをご覧ください。

60
Tim Pietzcker