我该如何在Perl字符串中手动插值转义字符?

5

在Perl中,假设我有一个字符串'hello\tworld\n',我想要的是:

'hello  world
'

也就是说,字符串应该是 "hello",然后是一个制表符,然后是 "world",然后是一个换行符。或者等价于 "hello\tworld\n"(注意双引号)。
换句话说,是否有一个函数可以接受具有转义序列的字符串,并返回一个等效的字符串,其中所有转义序列都被插值?我不想插值变量或其他任何东西,只想插值转义序列,比如 \x,其中 x 是一个字母。
2个回答

8
听起来像是别人已经解决的问题。 这个 模块看起来很有用,虽然我从未使用过。
use String::Escape qw(unbackslash);
my $s = unbackslash('hello\tworld\n');

非常感谢您。我找到了String::Interpolate,但那是完全不同的东西。 - Ryan C. Thompson
另外,对于在Ubuntu 9.10中使用此功能的人来说,String :: Escape的版本没有“unbackslash”。而是有“unprintable”。 - Ryan C. Thompson

2
你可以使用 'eval' 来实现这个功能:
my $string = 'hello\tworld\n';
my $decoded_string = eval "\"$string\"";

请注意,如果您无法100%控制输入字符串,则会与该方法相关的安全问题。
编辑:如果您仅想插值 \x 替换(而不是引用字符串中的任何Perl插值情况),可以执行此操作:
my $string = 'hello\tworld\n';
$string =~ s#([^\\A-Za-z_0-9])#\\$1#gs;
my $decoded_string = eval "\"$string\"";

这段代码几乎和quotemeta函数相同,但是它免除了对'\'字符的转义。

编辑2:尽管如此,这仍然不是100%安全的,因为如果最后一个字符是'\',它将会“泄漏”到字符串末尾之外...

个人而言,如果我想要100%的安全性,我会使用特定替换的哈希表,并使用正则表达式替换而非eval函数:

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

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

我可以安全地使用evalquotemeta的组合来实现这个吗?基本上,(my $interpolated_string = eval(q(") . quotemeta($string) . q("))) =~ s/\\(.)/\1/g - Ryan C. Thompson
不过这样做会把插值也破坏掉。 ;) - Snowhare
好的,我只想插值\x,其中x是任何字母。不包括变量或其他东西。 - Ryan C. Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接