【发布时间】:2012-03-06 22:51:59
【问题描述】:
短版:这是一个最小的失败示例:
$> 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
为什么会失败,如何让 Perl 脚本接受 ó 和 \w?
长版:我正在使用 Perl (5.10) 从 HTML 中抓取数据。 最终目标是让字符串仅表示为 ASCII 可打印集 (0x20-0x7F)。 这将涉及更改,例如ó 到 ó并且还通过将某些字符映射到近似值,例如各种空格以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 的输出中。当我注意到一些我完全不理解的字符被乱序编码时,它变得更奇怪了。这里有两个 hexdump(UNIX hexdump 实用程序)用于比较:
拉特 => 61 52 74 6c
Réalt => c3 52 61 a9 74 6c
WTF?
另外,这是我之前提到的那个该死的撇号。
拍拍 => 61 50 73 74
帕特 => 61 50 e2 74 99 80
这是我的问题:
- 疯狂的乱序编码是怎么回事?
- 我可以将 Perl 配置为在 s/ó/ó/g 等正则表达式中接受上述字符串吗?
- 我可以做些什么来转换,例如Pat's 变成 Pat's 并且基本上把它全部变成 ASCII,用 HTML 实体表示通常的重音元音?
对于第 2 部分,我可以确认我的键盘使用与读入的文件相同的编码将 ó 输入到文本编辑器中。
对于第 3 部分,完全没有必要留在 Perl 中。我也只需要像撇号这样的常见标点符号的映射。任何没有明显 ASCII 等价物的奇异字符都是意外的,应该会简单地触发失败。
【问题讨论】:
-
示例输入和完整的工作程序将帮助我们了解您做错了什么。
-
如果
"ó" =~ /\W/返回 true,那么你在某个地方搞砸了。可能您忘记将源代码放入 UTF-8 和 以使用use utf8声明它。还有其他可能的错误。至于编码错误,您在对数据文件的编码撒谎。对于这个问题,真的没有办法给你答案。 -
@briandfoy 请在我的帖子顶部查看编辑
标签: html perl utf-8 character-encoding utf