简短版本:这是一个最小的失败示例:
$> echo xóx > /tmp/input
$> hex /tmp/input
0x00000000: 78 c3 b3 78 0a
$> perl -e 'open F, "<", "/tmp/input" or die $!;
while(<F>) {
if ($_=~/x(\w)x/) {
print "Match:$1\n";
}else{
print "No match\n";
}
}'
No match
为什么这会失败?如何使用\w
使Perl脚本接受?
长版:我使用Perl(5.10)从HTML中抓取数据。 最终目标是将字符串专门表示为ASCII可打印集(0x20-0x7F)。这将涉及更改,例如ó到&amp; oacute;并且还通过将某些字符映射到近似值,例如各种空格最终为0x20
,某种类型的撇号(见后文)最终应该是普通的0x27
。
我的任务开始时“ó”=〜/ \ W /返回true,这让我感到惊讶,因为perldoc perlretut
告诉我
\ w匹配单词字符(字母数字或
_
),而不仅仅是[0-9a-zA-Z_],还包括非罗马字母中的数字和字符
我认为它与字符编码有关。我对此知之甚少,但源HTML包含
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
并且一个hexdump告诉我ó被编码为b3c3
而不是f3
,正如我最初预期的那样。
在Perl中,我尝试使用open F, "<:encoding(UTF-8)", $f
解决此问题,但这会给我带来错误,例如
utf8 "\xF3" does not map to Unicode
和\xF3
之类的字符串出现在read
的输出中。当我注意到一些字符按顺序编码时,它变得更加嘈杂,我根本不理解。这里有两个hexdumps(UNIX hexdump
实用程序)用于比较:
Ralt =&gt; 61 52 74 6c
Réalt=&gt; c3 52 61 a9 74 6c
WTF?
另外,这是我之前提到过的该死的撇号。
Pats =&gt; 61 50 73 74
Pat's =&gt; 61 50 e2 74 99 80
对于第2部分,我可以使用与读入的文件相同的编码确认我的键盘进入文本编辑器。
对于第3部分,保留在Perl中并不是必需的。我也只需要像撇号这样的常见标点符号的映射。没有明显的ASCII等价物的任何外来字符都是意外的,应该只是触发失败。
答案 0 :(得分:3)
你的hexdumper很糟糕。使用合适的。
$ echo -n Réalt | hex
0000 52 c3 a9 61 6c 74 R..alt
$ echo -n Pat’s | hex
0000 50 61 74 e2 80 99 73 Pat...s
是的,配置为use utf8;
,因此Perl源代码中的文字ó
被视为字符。 s/ó/ó/g
工作正常,但你应该使用一个模块来处理如下的实体。
3
use utf8;
use HTML::Entities qw(encode_entities);
encode_entities 'Réalt'; # returns 'Réalt'
encode_entities 'Pat’s'; # returns 'Pat’s'
阅读http://p3rl.org/UNI以了解Perl中的编码主题。
答案 1 :(得分:0)
您获取该字符串(UTF-8编码为“xóx
”),并将其传递给需要一串Unicode代码点的正则表达式引擎。 “xóx
”的UTF-8编码为78 C3 B3 78 0A
,当被视为Unicode代码点时为“xóx
”。
你实际上想要将78 F3 78 0A
传递给正则表达式引擎,这可以通过一个名为“解码”的过程获得。
对于UTF-8环境中的单行,您可以使用-CS
:
perl -CSDA -ne'
if (/x(\w)x/) {
print "Match:$1\n";
} else {
print "No match\n";
}
' /tmp/input
对于脚本,您可以使用binmode
,也许通过use open
:
use utf8; # Source code is UTF-8
use open ':std', ':encoding(UTF-8)'; # Set encoding for STD*
use open IO => ':encoding(UTF-8)'; # Default encoding for files
while (<>) {
if (/x(\w)x/) {
print "Match:$1\n";
} else {
print "No match\n";
}
}
始终解码您的输入。始终对输出进行编码。
至于您的其他问题,您可以使用HTML::Entities将文本转换为HTML实体(一旦解码完毕)。
请注意,对“&
”,“<
”,“>
”,“"
”和“{{1}以外的字符进行编码有点愚蠢因为你使用
'