Come sfuggire il simbolo del dollaro ($) in una stringa usando regex perl

Sto cercando di sfuggire a diversi caratteri speciali in una determinata stringa usando regex perl. Funziona bene per tutti i personaggi ad eccezione del simbolo del dollaro. Ho provato il seguente:

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; 

Prova questo:

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

Sembra strano, vero? Il tuo regex ha bisogno di apparire come segue:

 s/\$/\$/g 

Nella prima parte della regex, “$” ha bisogno di essere sfuggito, perché è un carattere regex speciale che indica la fine della stringa.

La seconda parte della regex è considerata una stringa “normale”, dove “$” non ha un significato speciale. Quindi il backslash è un vero backslash, mentre nella prima parte viene utilizzato per sfuggire al segno del dollaro.

Inoltre nella definizione della variabile è necessario sfuggire al backslash e al simbolo del dollaro, poiché entrambi hanno un significato speciale nelle stringhe con virgolette doppie.

Non hai bisogno di un hash se stai sostituendo ogni personaggio con se stesso preceduto da un backslash. Basta abbinare ciò che ti serve e mettere una barra rovesciata di fronte ad esso:

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

Per build l’espressione regolare per tutti i personaggi, Regexp :: Assemble è davvero bello.

 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(  ) { s/($re)/"\\$1"/eg; print; } __DATA__ There are $100 dollars Part #1234 Outside { inside } Outside 

Si noti come, nella prima riga di input, Regexp :: Assemble abbia riorganizzato il mio pattern. Non sono solo i pezzi incollati delle parti che ho aggiunto:

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

Se vuoi aggiungere più personaggi, inserisci il carattere in @specials . Tutto il resto accade per te.

$ ha un significato speciale in regexp, ovvero “end of string”. Saresti meglio con qualcosa del genere:

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

Inoltre, perl non piace "$" molto, meglio usare '$' (virgolette singole => nessuna interpolazione).

AGGIORNAMENTO: Scusa, stavo scrivendo questo in fretta => troppe modifiche 🙁