web-dev-qa-db-ja.com

Perl正規表現を使用して文字列内のドル記号($)をエスケープする方法

Perl正規表現を使用して、特定の文字列内のいくつかの特殊文字をエスケープしようとしています。ドル記号を除くすべての文字で正常に機能します。私は以下を試しました:

my %special_characters;
$special_characters{"_"} = "\\_";
$special_characters{"$"} = "\\$";
$special_characters{"{"} = "\\{";
$special_characters{"}"} = "\\}";
$special_characters{"#"} = "\\#";
$special_characters{"%"} = "\\%";
$special_characters{"&"} = "\\&";

my $string = '$foobar';
foreach my $char (keys %special_characters) {
  $string =~ s/$char/$special_characters{$char}/g;
}
print $string;
16
Tom Winter

これを試して:

my %special_characters;
$special_characters{"_"} = "\\_";
$special_characters{"\\\$"} = "\\\$";
$special_characters{"{"} = "\\{";
$special_characters{"}"} = "\\}";
$special_characters{"#"} = "\\#";
$special_characters{"%"} = "\\%";
$special_characters{"&"} = "\\&";

奇妙に見えますか?正規表現は次のようにする必要があります。

s/\$/\$/g

正規表現の最初の部分では、「$」は文字列の終わりを示す特別な正規表現文字であるため、エスケープする必要があります。

正規表現の2番目の部分は「通常の」文字列と見なされます。「$」には特別な意味はありません。したがって、バックスラッシュは実際のバックスラッシュですが、最初の部分ではドル記号をエスケープするために使用されています。

さらに、変数の定義では、バックスラッシュとドル記号をエスケープする必要があります。これらは両方とも、二重引用符で囲まれた文字列で特別な意味を持つためです。

20
laurent

各文字をバックスラッシュが前に付いた文字で置き換える場合は、ハッシュは必要ありません。必要なものに一致させ、その前にバックスラッシュを置きます。

s/($re)/"\\$1"/eg;

すべての文字の正規表現を作成するには、 Regexp :: Assemble が最適です。

use v5.10.1;
use Regexp::Assemble;

my $ra = Regexp::Assemble->new;

my @specials = qw(_ $ { } # % & );

foreach my $char ( @specials ) {
    $ra->add( "\\Q$char\\E" );
    }

my $re = $ra->re;
say "Regex is $re"; 

while( <DATA> ) {
    s/($re)/"\\$1"/eg;
    print;
    }

__DATA__
There are $100 dollars
Part #1234
Outside { inside } Outside

入力の1行目で、Regexp :: Assembleがパターンを再配置したことに注目してください。それは、私が追加したパーツのほんの一部を接着しただけではありません。

Regex is (?^:(?:[#$%&_]|\{|\}))
There are \$100 dollars
Part \#1234
Outside \{ inside \} Outside

さらに文字を追加したい場合は、その文字を@specials。他のすべてはあなたのために起こります。

3
brian d foy

$は、正規表現で特別な意味を持っています。つまり、「文字列の終わり」です。あなたはこのようなものでうまくいくでしょう:

# escape special characters, join them into a single line
my $chars = join '', map { "\\$_" } keys %special_characters;
$string =~ s/([$chars])/$special_characters{$1}/g;

また、Perlは"$"をあまり好きではありません。'$'を使用することをお勧めします(一重引用符=>補間なし)。

PDATE:すみません、急いでこれを書いていました=>編集が多すぎます:(

0
Dallaylaen