如何将转义字符转换为Perl中的实际特殊字符?
可能重复:
How can I manually interpolate string escapes in a Perl string?如何将转义字符转换为Perl中的实际特殊字符?
我读从一个特定的文件中的字符串。它的问题是它包含转义字符,如:
Hello!\nI\'d like to tell you a little \"secret\"...
我想它打印出来,而不转义序列,如:
Hello!
I'd like to tell you a little "secret".
我考虑去除单反斜线和更换双倍于单个(因为\被表示为\\),但是这对我\ n,\ t问题等没有帮助。在试图摆弄丑陋,复杂的替换字符串之前,我想我会问 - 也许Perl有这种转换的内置机制?
在Perl单个字符backslash escapes,你可以这样做安全使用两个字符eval
作为替代的一部分。您需要在\
之后放入可接受的字符类中解释的字符,然后是eval
'd后面的单个字符并插入到字符串中。
考虑:
#!/usr/bin/perl
use warnings;
use strict;
print "\n\n\n\n";
while (my $data = <DATA>) {
$data=~s/\\([rnt'"\\])/"qq|\\$1|"/gee;
print $data;
}
__DATA__
Hello!\nI\'d like to tell you a little \"secret\".
A backslask:\\
Tab'\t'stop
line 1\rline 2 (on Unix, "line 1" will get overwritten)
line 3\\nline 4 (should result in "line 3\\nline 4")
line 5\r\nline 6
输出:
Hello!
I'd like to tell you a little "secret".
A backslask:\
Tab' 'stop
line 2 (on Unix, "line 1" will get overwritten)
line 3\nline 4 (should result in "line 3\nline 4")
line 5
line 6
线s/\\([rnt'"\\])/"qq|\\$1|"/gee
做的工作。
\\([rnt'"\\])
有大括号内的可接受字符。的
gee
部分确实对替换字符串的双重EVAL。的
"qq|\\$1|"
部分eval'd两次。第一个eval
将$1
替换为字符串,第二个执行插值。
我想不出一个两个字符的组合,这将是一个安全漏洞...
这种方法确实不处理正确执行以下操作:
带引号的字符串。例如,由于单引号,Perl不会忽略字符串'line 1 \ nline 2'。
逃逸序列,其比单个字符较长,如十六进制
\x1b
或Unicode如\N{U+...}
或控制序列,例如\cD
锚逃逸,如\ LMAKE小写\ E或\ Umake上案例。\ E
如果你想更完整的越狱更换,你可以使用这个表达式:
#!/usr/bin/perl
use warnings;
use strict;
print "\n\n\n\n";
binmode STDOUT, ":utf8";
while (my $data = <DATA>) {
$data=~s/\\(
(?:[arnt'"\\]) | # Single char escapes
(?:[ul].) | # uc or lc next char
(?:x[0-9a-fA-F]{2}) | # 2 digit hex escape
(?:x\{[0-9a-fA-F]+\}) | # more than 2 digit hex
(?:\d{2,3}) | # octal
(?:N\{U\+[0-9a-fA-F]{2,4}\}) # unicode by hex
)/"qq|\\$1|"/geex;
print $data;
}
__DATA__
Hello!\nI\'d like to tell you a little \"secret\".
Here is octal: \120
Here is UNICODE: \N{U+0041} and \N{U+41} and \N{U+263D}
Here is a little hex:\x50 \x5fa \x{5fa} \x{263B}
lower case next char \lU \lA
upper case next char \ua \uu
A backslask:\\
Tab'\t'stop
line 1\rline 2 (on Unix, "line 1" will get overwritten)
line 3\\nline 4 (should result in "line 3\\nline 4")
line 5\r\nline 6
处理所有的Perl escapes除了:
锚型(\ Q,\ü通过。\ E结束,\ L)
引用形式,如
'don't \n escape in single quotes'
或[not \n in here]
命名为unicode字符,如
\N{THAI CHARACTER SO SO}
控制字符如
\cD
(即容易加到...)
但是,这不是你的问题的一部分,因为我的理解是......
我不建议这样做,但字符串eval
可以解决问题,但字符串eval
会引发大量安全和维护问题。这些数据来自哪里?数据生产者和你之间是否有任何关于字符串将保持的合同?
#!/usr/bin/perl
use strict;
use warnings;
while (my $input = <DATA>) {
#note: this only works if # is not allowed as a character in the string
my $string = eval "qq#$input#" or die [email protected];
print $string;
}
__DATA__
Hello!\nI\'d like to tell you a little \"secret\".
This is bad @{[print "I have pwned you\n"]}.
另一个解决方案是创建一个哈希定义所有你想要实现和做一个替代的逃逸。
第一次替换效果很好,谢谢! – Neo 2010-10-03 15:44:30