web-dev-qa-db-fra.com

Comment échapper au signe dollar ($) dans une chaîne en utilisant une expression rationnelle Perl

J'essaie d'échapper à plusieurs caractères spéciaux dans une chaîne donnée en utilisant une expression rationnelle Perl. Cela fonctionne très bien pour tous les personnages sauf le signe dollar. J'ai essayé ce qui suit:

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;
15
Tom Winter

Essaye ça:

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

Ça a l'air bizarre, non? Votre regex doit ressembler à ceci:

s/\$/\$/g

Dans la première partie de la regex, "$" doit être échappé, car il s'agit d'un caractère de regex spécial indiquant la fin de la chaîne.

La deuxième partie de l'expression rationnelle est considérée comme une chaîne "normale", où "$" n'a pas de signification particulière. Par conséquent, la barre oblique inversée est une vraie barre oblique inversée alors que dans la première partie, elle est utilisée pour échapper au signe dollar.

De plus, dans la définition de variable, vous devez échapper à la barre oblique inversée ainsi qu'au signe dollar, car les deux ont une signification particulière dans les chaînes entre guillemets.

18
laurent

Vous n'avez pas besoin d'un hash si vous remplacez chaque caractère par un caractère précédé d'une barre oblique inverse. Faites simplement correspondre ce dont vous avez besoin et mettez une barre oblique inverse devant celui-ci:

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

Pour construire l'expression régulière de tous les caractères, Regexp :: Assemble est vraiment gentil.

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

Remarquez comment, dans la première ligne, Regexp :: Assemble a réarrangé mon motif. Ce ne sont pas seulement les morceaux collés des parties que j'ai ajoutées:

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

Si vous voulez ajouter plus de caractères, il vous suffit de le mettre dans @specials. Tout le reste arrive pour vous.

3
brian d foy

$ a une signification spéciale dans l'expression rationnelle, à savoir "fin de chaîne". Vous seriez mieux avec quelque chose comme ça: 

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

En outre, Perl n'aime pas beaucoup "$", il vaut mieux utiliser '$' (guillemets simples => pas d'interpolation). 

UPDATE: Désolé, j'écrivais ceci rapidement:> trop de modifications :(

0
Dallaylaen