\ x不在替换内部工作

时间:2016-10-12 06:59:44

标签: regex perl unicode

我正在尝试解码unicode字符。所以我只是在正则表达式替换\x{}

中尝试了十六进制转义序列e
use LWP::Simple;
my $k = get("url");

my ($kv) =map{/js_call\(\\"(.+?)\\"\)/} $k;

#now $kv data is https://someurl/call.pl?id=15967737\u0026locale=en-GB\u0026mkhun=ccce

$kv=~s/\\u(.{4})/"\x{$1}"/eg;

我正在尝试替换所有unicode角色。

我的预期输出是:

https://someurl/call.pl?id=15967737&locale=en-GB&mkhun=ccce

下面提到的print语句给出了预期的输出。然而,正则表达式似乎无法正常工作。

print "\x{0026}";

3 个答案:

答案 0 :(得分:7)

s/\\u(.{4})/"\x{$1}"/e的问题是在编译时计算反斜杠转义\x{$1},这给出了一个NULL字节:

$ perl -E 'printf "%vX\n", "\x{$1}"'
0

如果我们在xs/\\u(.{4})/"\\x{$1}"/ge)前面转义反斜杠,我们会得到一个包含文字转义序列的字符串,但仍然不是所需的unicode字符:

use feature qw(say);
$kv = '\u0026';
$kv =~ s/\\u(.{4})/"\\x{$1}"/ge;
say $kv; 

输出现在是:

\x{0026}

通过一个小的修改,您可以生成"\x{0026}",这是您可以编译和执行的Perl代码,以生成所需的值。为此,您需要参与eval(EXPR)

$kv =~ s/\\u(.{4})/ my $s = eval(qq{"\\x{$1}"}); die $@ if $@; $s /ge;

这可以缩短为

$kv =~ s/\\u(.{4})/ qq{"\\x{$1}"} /gee;

然而,更好的解决方案是使用以下内容:

$kv =~ s/\\u(.{4})/chr hex $1/ge;

答案 1 :(得分:2)

如果您启用use warnings,您会看到$1在反向引用进行插值之前按字面意义进行评估。

$kv =~ s/\\u(.{4})/ sprintf("\"\\x{%s}\"", $1) /eeg;

有点作品,但它很丑陋。我一直试图简化它,但我尝试过的各种想法总让我回到了非法的十六进制数字' $'忽略"警告。

答案 2 :(得分:2)

也许你可以试试这个:

$kv=~s/\\u([[:xdigit:]]{1,5})/chr(eval("0x$1"))/egis;

感谢。