Regexp不适用于Perl中的特定特殊字符

时间:2011-11-25 13:45:17

标签: regex perl unicode special-characters

我无法在字符串中删除特殊字符¤

$word = 'cɞi¤r$c❤u¨s';
$word =~ s/[^a-zöäåA-ZÖÄÅ]//g;
printf "$word\n";

在第二行,我尝试从字符串$word中删除任何非字母字符。我希望打印出 circus 这个词,但我得到了:

ci�rc�us

表达式中的öäåÖÄÅ只是我需要的瑞典语字母中的普通字符。

3 个答案:

答案 0 :(得分:11)

如果您的源代码中包含字符,请务必use utf8。如果正在从文件中读取binmode $FILEHANDLE, ':utf8'

请务必阅读perldoc perlunicode

答案 1 :(得分:3)

简答:添加使用utf8;确保源代码中的文字字符串被解释为utf8,其中包括测试字符串的内容和正则表达式的内容。

答案很长:

#!/usr/bin/env perl

use warnings;
use Encode;

my $word = 'cɞi¤r$c❤u¨s';

foreach my $char (split //, $word) {
    print ord($char) . Encode::encode_utf8(":$char ");
}

my $allowed_chars = 'a-zöäåA-ZÖÄÅ';

print "\n";

foreach my $char (split //, $allowed_chars) {
    print ord($char) . Encode::encode_utf8(":$char ");
}

print "\n";

$word =~ s/[^$allowed_chars]//g;

printf Encode::encode_utf8("$word\n");

不使用utf8执行它:

$ perl utf8_regexp.pl
99:c 201:É 158: 105:i 194:Â 164:¤ 114:r 36:$ 99:c 226:â 157: 164:¤ 117:u 194:Â 168:¨ 115:s 
97:a 45:- 122:z 195:Ã 182:¶ 195:Ã 164:¤ 195:Ã 165:¥ 65:A 45:- 90:Z 195:Ã 150: 195:Ã 132: 195:Ã 133: 
ci¤rc¤us

用utf8执行它:

$ perl -Mutf8 utf8_regexp.pl
99:c 606:ɞ 105:i 164:¤ 114:r 36:$ 99:c 10084:❤ 117:u 168:¨ 115:s 
97:a 45:- 122:z 246:ö 228:ä 229:å 65:A 45:- 90:Z 214:Ö 196:Ä 197:Å 
circus

说明:

您在源代码中键入的非ascii字符由一个以上的字节表示。由于您的输入是utf8编码。在纯粹的ascii或latin-1终端中,字符将是一个字节。

当不使用utf8模块时,perl认为您输入的每个字节都是一个单独的字符,就像您在分割和打印每个字符时所看到的那样。使用utf8模块时,它会根据utf8编码规则将几个字节的组合正确地视为一个字符。

正如你可以看到的那样,瑞典字符组成的一些字节与测试字符串中某些字符组成的一些字节相匹配,并保留它们。即:ö其中utf8由195:Ã164:¤ - 164最终作为你允许的角色之一并且它通过。

解决方法是告诉perl你的字符串应该被认为是utf-8。

编码encode_utf8是为了避免警告有关打印到终端的宽字符。与往常一样,您需要解码输入,并根据输入或输出应处理/操作的字符编码对输出进行编码。

希望这更清楚。

答案 2 :(得分:-7)

作为pointed out by choroba,在perl脚本的开头添加它可以解决它:

use utf8;
binmode(STDOUT, ":utf8");

其中use utf8允许您在正则表达式中正确使用特殊字符,binmode(STDOUT, ":utf8")允许您在shell上正确输出特殊字符。