16

我正在尝试使用 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;
4

3 回答 3

22

尝试这个:

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

看起来很奇怪,对吧?您的正则表达式需要如下所示:

s/\$/\$/g

在正则表达式的第一部分,“$”需要转义,因为它是一个特殊的正则表达式字符,表示字符串的结尾。

正则表达式的第二部分被视为“普通”字符串,其中“$”没有特殊含义。因此,反斜杠是一个真正的反斜杠,而在第一部分中,它用于转义美元符号。

此外,在变量定义中,您需要转义反斜杠和美元符号,因为它们在双引号字符串中都有特殊含义。

于 2012-03-15T09:01:19.970 回答
3

如果您将每个字符替换为前面带有反斜杠的自身,则不需要哈希。只需匹配您需要的内容并在其前面加上反斜杠:

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

请注意,在输入的第一行中,Regexp::Assemble 是如何重新排列我的模式的。这不仅仅是我添加的部分的粘合在一起:

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

如果要添加更多字符,只需将字符放入@specials. 其他一切都发生在你身上。

于 2012-03-15T15:07:49.140 回答
0

$在正则表达式中具有特殊含义,即“字符串结尾”。使用这样的方法会更好:

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

此外,perl 不太喜欢"$"更好地使用'$'(单引号 => 无插值)。

更新:对不起,我写的很匆忙=>编辑太多:(

于 2012-03-15T09:05:18.683 回答