How can I manually interpolate string escapes in a

2019-01-07 00:26发布

问题:

In perl suppose I have a string like 'hello\tworld\n', and what I want is:

'hello  world
'

That is, "hello", then a literal tab character, then "world", then a literal newline. Or equivalently, "hello\tworld\n" (note the double quotes).

In other words, is there a function for taking a string with escape sequences and returning an equivalent string with all the escape sequences interpolated? I don't want to interpolate variables or anything else, just escape sequences like \x, where x is a letter.

回答1:

Sounds like a problem that someone else would have solved already. I've never used the module, but it looks useful:

use String::Escape qw(unbackslash);
my $s = unbackslash('hello\tworld\n');


回答2:

You can do it with 'eval':

my $string = 'hello\tworld\n';
my $decoded_string = eval "\"$string\"";

Note that there are security issues tied to that approach if you don't have 100% control of the input string.

Edit: If you want to ONLY interpolate \x substitutions (and not the general case of 'anything Perl would interpolate in a quoted string') you could do this:

my $string = 'hello\tworld\n';
$string =~ s#([^\\A-Za-z_0-9])#\\$1#gs;
my $decoded_string = eval "\"$string\"";

That does almost the same thing as quotemeta - but exempts '\' characters from being escaped.

Edit2: This still isn't 100% safe because if the last character is a '\' - it will 'leak' past the end of the string though...

Personally, if I wanted to be 100% safe I would make a hash with the subs I specifically wanted and use a regex substitution instead of an eval:

my %sub_strings = (
    '\n' => "\n",
    '\t' => "\t",
    '\r' => "\r",
);

$string =~ s/(\\n|\\t|\\n)/$sub_strings{$1}/gs;