2

ここに小さな perl スニペットがあります:

my $n = 1;
my $re_str = '\d';
my $re_str_q = '\Q1\E';

printf "re_str   match: %s\n", ($n =~ /$re_str/);
printf "re_str_q match: %s\n", ($n =~ /$re_str_q/);
printf "direct match: %s\n", ($n =~ /\Q1\E/);

実行すると、次の出力が生成されます。

re_str   match: 1
re_str_q match: 
direct match: 1

だから、ここでの私の質問は、なぜ2番目printfが一致しないのですか?

4

5 に答える 5

3

\Q は正規表現エスケープではなく、文字列で置換される文字列エスケープであるため、"\Q1\E" は quotemeta('1') と同等です。

したがって、"" や qr// などのシーケンスを補間できる引用符を使用するか、文字列エスケープを使用する代わりに quotemeta を呼び出す必要があります。

于 2013-05-28T15:24:29.640 に答える
2

正規表現には 2 種類のエスケープがあります。

  • リテラルの解析時に処理されるエスケープ。
  • 正規表現エンジンによって処理されるエスケープ。

例えば、

  • \Q..\E前者の種類です。
  • \dは後者の種類です。
  • \nどちらも親切です。

つまり、

  • "abc\Q!@#\Edef"12 文字の文字列を生成しますabc\!\@\#def
  • qq/abc\Q!@#\Edef/はまったく同じことです。
  • qr/abc\Q!@#\Edef/12 文字の文字列を生成し、abc\!\@\#defそれを 9 文字に一致する正規表現パターンとしてコンパイルしますabc!@#def

しかし、一重引用符はそのようなエスケープを処理しないので、

  • 'abc\Q!@#\Edef'13 文字の文字列を生成しますabc\Q!@#\Edef

\Q正規表現エンジンはorを認識しないため\E、最後の文字列を渡すと警告が表示され、11 文字との一致が試行されますabcQ!@#Edef

修正は変更することです

my $re_str   = '\d';         # Produces string \d
my $re_str_q = '\Q1\E\';     # Produces string \Q1\E

my $re_str   = "\\d";        # Produces string \d
my $re_str_q = "\Q1\E";      # Produces string \1

またはさらに良いことに、

my $re_str   = qr/\d/;       # Produces regex \d
my $re_str_q = qr/\Q1\E/;    # Produces regex \1

詳細については、\具体的にお読みください。

于 2013-05-28T16:38:11.280 に答える