Perl: quoting correctly all special characters

399 views Asked by At

I have this sample string, containing 2 backslashes. Please don't ask me for the source of the string, it is just a sample string.

my $string = "use Ppppp\\Ppppp;";
print $string;

Both, double quotes or quotes will print

use Ppppp\Ppppp;

Using

my $string = "\Quse Ppppp\\Ppppp;\E";
print $string;

will print

use\ Ppppp\\Ppppp\;

adding those extra backslashes to the output.

Is there a simple solution in perl to display the string "literally", without modifying the string like adding extra backslashes to escape?

1

There are 1 answers

2
haukex On

I have this sample string, containing 2 backslashes. ...

my $string = "use Ppppp\\Ppppp;";

Sorry, but you're mistaken - that string only contains one backslash*, as \\ is a escape sequence in double-quoted (and single-quoted) strings that produces a single backslash. See also "Quote and Quote-like Operators" in perlop. If your string really does contain two backslashes, then you need to write "use Ppppp\\\\Ppppp;", or use a heredoc, as in:

chomp( my $string = <<'ENDSTR' );
use Ppppp\\Ppppp;
ENDSTR

If you want the string output as valid Perl source code (using its escaping), then you can use one of several options:

my $string = "use Ppppp\\Ppppp;";
# option 1
use Data::Dumper;
$Data::Dumper::Useqq=1;
$Data::Dumper::Terse=1;
print Dumper($string);
# option 2
use Data::Dump;
dd $string;
# option 3
use B;
print B::perlstring($string);

Each one of these will print "use Ppppp\\Ppppp;". (There are of course other modules available too. Personally I like Data::Dump. Data::Dumper is a core module.)

Using one of these modules is also the best way to verify what your $string variable really contains.

If that still doesn't fit your needs: A previous edit of your question said "How can I escape correctly all special characters including backslash?" - you'd have to specify a full list of which characters you consider special. You could do something like this, for example:

use 5.014; # for s///r
my $string = "use Ppppp\\Ppppp;";
print $string=~s/(?=[\\])/\\/gr;

That'll print $string with backslashes doubled, without modifying $string. You can also add more characters to the regex character class to add backslashes in front of those characters as well.

* Update: So I don't sound too pedantic here: of course the Perl source code contains two backslashes. But there is a difference between the literal source code and what the Perl string ends up containing, the same way that the string "Foo\nBar" contains a newline character instead of the two literal characters \ and n.

For the sake of completeness, as already discussed in the comments: \Q\E (aka quotemeta) is primarily meant for escaping any special characters that may be special to regular expressions (all ASCII characters not matching /[A-Za-z_0-9]/), which is why it is also escaping the spaces and semicolon.

Since you mention external files: If you are reading a line such as use Ppppp\\Ppppp; from an external file, then the Perl string will contain two backslashes, and if you print it, it will also show two backslashes. But if you wanted to represent that string as Perl source code, you have to write "use Ppppp\\\\Ppppp;" (or use one of the other methods from the question you linked to).