Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to escape dollar sign ($) in a string using perl regex

I'm trying to escape several special characters in a given string using perl regex. It works fine for all characters except for the dollar sign. I tried the following:

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;
like image 742
Tom Winter Avatar asked Mar 15 '12 08:03

Tom Winter


People also ask

How do you escape the dollar sign in regex?

You can escape dollar signs with a backslash or with another dollar sign. So $, $$, and \$ all replace with a single dollar sign.

How do I get rid of the dollar sign in Perl?

Just match what you need and put a backslash in front of it: s/($re)/"\\$1"/eg; To build up the regular expression for all of the characters, Regexp::Assemble is really nice.

How do you escape a special character in Perl?

The backslash is the escape character and is used to make use of escape sequences. When there is a need to insert the escape character in an interpolated string, the same backslash is used, to escape the substitution of escape character with ” (blank). This allows the use of escape character in the interpolated string.

What is the meaning of $1 in Perl regex?

$1 equals the text " brown ".


3 Answers

Try this:

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

Looks weird, right? Your regex needs to look as follows:

s/\$/\$/g

In the first part of the regex, "$" needs to be escaped, because it's a special regex character denoting the end of the string.

The second part of the regex is considered as a "normal" string, where "$" doesn't have a special meaning. Therefore the backslash is a real backslash whereas in the first part it's used to escape the dollar sign.

Furthermore in the variable definition you need to escape the backslash as well as the dollar sign, because both of them have special meaning in double-quoted strings.

like image 57
laurent Avatar answered Oct 12 '22 21:10

laurent


You don't need a hash if you're replacing each character with itself preceded by a backslash. Just match what you need and put a backslash in front of it:

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

To build up the regular expression for all of the characters, Regexp::Assemble is really nice.

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

Notice how, in the first line of input, Regexp::Assemble has re-arranged my pattern. It's not just the glued together bits of the parts I added:

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

If you want to add more characters, you just put the character in @specials. Everything else happens for you.

like image 3
brian d foy Avatar answered Oct 12 '22 20:10

brian d foy


$ has special meaning in regexp, namely "end of string". You would be better off with something like this:

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

Also, perl doesn't like "$" much, better use '$' (single quotes => no interpolation).

UPDATE: Sorry, I was writing this in a hurry => too many edits :(

like image 1
Dallaylaen Avatar answered Oct 12 '22 22:10

Dallaylaen