Perl m//のPerl変数の拡張

Perl m//のPerl変数の拡張

m//Perlは一致演算子内で変数拡張をどのように実行しますか?私が読んだのは、m//変数の拡張/補間が一度だけ行われることです。ところで、拡張するUnmatched ( in regexとなぜ表示されますか$pat

my $pat = '(\\)';
'\\' =~ /(\\)/  ? print "OK\n" : print "NO MATCH!\n";   # OK
'\\' =~ /$pat/  ? print "OK\n" : print "NO MATCH!\n";   # Unmatched ( in regex

my $pat2 = '(\\\)';
'\\' =~ /$pat2/  ? print "OK\n" : print "NO MATCH!\n";  # OK

答え1

問題は、バックスラッシュの難解なルールを誤って適用したり、誤って覚えていることです。

一重引用符で囲まれた文字列リテラル

バックスラッシュは、区切り記号または他のバックスラッシュが後に来ない限りバックスラッシュを意味します。この場合、区切り記号またはバックスラッシュが挿入されます。

したがって、ソースコードのバックスラッシュの後には、単一のバックスラッシュを表す別のバックスラッシュが続くため、値は$pat3文字の文字列です。ソースコードの最初の2つのバックスラッシュは1つのバックスラッシュを表し、その後に3番目のバックスラッシュが続くため、(\)値は$pat24文字の文字列です。したがって、文字列内の2番目のバックスラッシュとして単独で使用されます。(\\))

正規表現、バックスラッシュは英数字でない限り、次の文字を引用します。/$pat/同様に/(\)/、これは開始グループであり、その後にリテラル閉じ括弧が続き、グループ)の閉じ括弧はありません。開いたグループ、バックスラッシュ、または閉じたグループ/$pat2/と同じです。/(\\)/

答え2

に割り当てると、$pat最初のバックスラッシュが2番目のバックスラッシュをエスケープするため、結果の文字列には1つのバックスラッシュしか含まれません。正規表現を処理するときに閉じる角かっこをエスケープして、キャプチャグループを閉じるためにエスケープされていない角かっこを残しません。

つまり、m//バックスラッシュは一度だけ解釈されますが、内側でも解釈されるため、合計で'...'2回処理されます。

$ cat p.pl 
$pat = '(\\)'; print $pat
$ perl -l p.pl 
(\)

~から手動:

引用演算子
q/STRING/
'STRING'
一重引用符で囲まれたリテラル文字列。バックスラッシュは、区切り記号または他のバックスラッシュが後に来ない限りバックスラッシュを意味します。この場合、区切り記号またはバックスラッシュが挿入されます。

(もちろん、これはシェルでバックスラッシュと一重引用符がどのように機能するかとは異なります。)

関連情報