1

この単純な正規表現プログラム

import java.util.regex.*;
class Regex {
    public static void main(String [] args) {
        System.out.println(args[0]); // #1
        Pattern p = Pattern.compile(args[0]); // #2
        Matcher m = p.matcher(args[1]);
        boolean b = false;
        while(b = m.find()) {
            System.out.println(m.start()+" "+m.group());
        }
    }
}

によって呼び出されjava regex "\d" "sfdd1"、正常に実行されます。

ただし、#1をに置き換えるPattern p = Pattern.compile("\d");と、不正なエスケープ文字を示すコンパイラエラーが発生します。#1では、コマンドライン引数で指定されたパターンも出力してみました。を印刷します。これは、#2で\d置き換えられていることを意味します。\d

では、なぜ例外をスローしないのでしょうか。最後にPattern.compile()取っているのは文字列引数ですが、不正なエスケープ文字を検出しませんか?誰かがこの振る舞いの理由を説明できますか?

4

4 に答える 4

3

文字列リテラルのバックスラッシュ文字はエスケープする必要があります(バックスラッシュが前に付きます)。コマンドラインから渡された場合、文字列は文字列リテラルではありません。"\d"は有効なエスケープシーケンスではないため、コンパイラは文句を言います(文字および文字列リテラルのエスケープシーケンスを参照)。

于 2012-09-24T21:36:12.403 に答える
1

この\文字は、Java文字列リテラルと正規表現の両方のエスケープ文字として使用されます。これは多くのプログラマーを混乱させます。エスケープ文字を持つ正規表現を表す文字列をJavaで作成する場合は、Javaエスケープ文字をエスケープする必要があります。

コマンドラインで文字列を渡すと、JVMがこれを処理し、文字列を作成するだけです。

あなたが欲しいのはこれです

Pattern p = Pattern.compile("\\d");
于 2012-09-24T21:44:20.443 に答える
1

\Javaのバックスラッシュは、文字列のエスケープになります。たとえば、文字列"\t"はJavaのタブ文字になります。"\n"これが、改行を生成する理由でもあります。

正規表現では、はJavaではなく、正規表現に関する\dエスケープです。つまり、文字列リテラルを取得するには、文字列を入力する必要があります。基本的に、リテラル値を取得するにはをエスケープする必要があります。その後、正規表現をコンパイルすると、さらにエスケープされて数字として解析されます。\d"\\d"\\dPattern\d

これは紛らわしいかもしれませんが、簡単に言えば、文字列リテラルでさえ適切に解析される\ため、正規表現の文字列リテラルに単一を含めることはできません。"\\n"

于 2012-09-24T21:47:58.793 に答える
0

質問を理解できるかどうかは完全にはわかりませんが、問題は「\d」を存在しないJavaエスケープ文字として扱っていることのようです。正規表現のエスケープ文字として扱うには、「\d」を使用してJavaエスケープをエスケープします。

于 2012-09-24T21:36:35.700 に答える