设为首页 收藏本站
查看: 1326|回复: 0

[经验分享] 讨论perl中的utf-8编码处理

[复制链接]

尚未签到

发表于 2017-5-18 12:26:23 | 显示全部楼层 |阅读模式
  为了比较方便,考虑这样一个应用:把html页面中的所有非汉字字符全部去掉。
  这里顺便告诉大家一个秘诀,只要文本被perl按正确编码解释后,利用\w就可以匹配一个字母、数字、_、汉字,这个特性是不是很方便,所以我们只要用如下两次正则表达式就可以去掉所有非汉字字符,包括全角的一些标点(@#$%<,())也能去的很干净:

DSC0000.gif $str=~s/[^w]//g;
$str=~s/[0-9a-zA-Z_]//g;

  问题在于如何让perl正确的理解我们的文本,我先给出我们的测试程序如下:

#!/usr/bin/perl
usestrict;
useEncode;
useopenIN=>":raw",OUT=>":raw";

my$arg=$ARGV[0];
subaaa{
openFH,"testutf8"ordie"aaa$! ";
local$/=undef;
binmodeFH,":utf8";
my$str=<FH>;
return$str;
}
subbbb{
openFH,"testutf8";
local$/=undef;
binmodeFH,":raw";
my$str=<FH>;
$str=pack"U0C*",unpack"C*",$str;
return$str;
}
subccc{
openFH,"testutf8"ordie"aaa$! ";
local$/=undef;
binmodeFH,":raw";
my$str=<FH>;
$str=Encode::decode_utf8($str);
return$str;
}
subddd{
openFH,"testutf8"ordie"aaa$! ";
local$/=undef;
binmodeFH,":raw";
my$str=<FH>;
$str=decode('utf-8',$str);
return$str;
}
subeee{
openFH,"testgb"ordie"aaa$! ";
local$/=undef;
binmodeFH,":raw";
my$str=<FH>;
Encode
::from_to($str,'gbk','utf-8');
$str=Encode::decode_utf8($str);
return$str;
}
subfff{
my$str=`iconv-fgbk-tutf-8testgb`;
$str=Encode::decode_utf8($str);
return$str;
}
my$f;
eval("$f=*$arg");
for(my$i=0;$i<200;$i++){
my$str=&$f();
#print"$i",(length$str)." ";
}
my$str;
$str=&$f();
$str=~s/[^w]//g;
$str=~s/[0-9a-zA-Z_]//g;
print$str;

  这里共有aaa-fff六个方法,其中aaa-ddd四个方法是把一个叫testutf8的文本文件读入并转码,而eee-fff两个方法是读入testgb文本的。
  程序运行的时候,第一个参数传入方法名,像这样./test.pl aaa就可以了,在命令前面加time可以统计所花的时间。这里为了避免perl做的干扰,程序一开始用use open IN => ":raw", OUT => ":raw"; 强制默认的输入输出都不做解释。
  这六种方法都是经过测试能正确得到要求的结果的,但是运行速度在我的perl 5.8.0下却是不一样的,如下
  aaa 0m0.376s
bbb 0m5.263s
ccc 0m0.432s
ddd 0m2.668s
eee 0m0.784s
fff 0m1.358s
  从结果我们可以看出,方法bbb最慢,它使用了某些文章上推崇的pack、unpack技巧,不仅从语法上来说极其恶心,效率也是最差
而方法ddd和ccc同样使用了Encode模块,做了同样的事,效率却差的很大,可见Encode模块还是存在缺陷的。也就是说decode方法比decode_utf8方法慢的太多了。
方法aaa并没有太出色的表现,不过也居第一,说明perl底层对utf-8的直接支持还算行。
作为一个反映perl底层糟糕的例子,把":utf8"改成":encoding(utf-8)"测试一下,用了0m1.650s,慢了400%
  作为更多的尝试,考虑一下GBK编码的例子,eee使用了一个迂回战术,先用from_to转成utf-8,然后直接调用decode_utf8以避开decode的调用,fff类似,只不过调用了iconv进程来转。
从这我们看出,linux的进程生成代价果然极低,fff方法的差距竟然比bbb的更小(意思是,perl中的不当编程,导致竟然比反复调用外部程序做的还慢)。
  那么decode是否真的很慢呢,把eee方法改动一下,直接调用encode,像这样
$str = Encode::decode('gbk', $str);
我们发现,时间是0m0.727s,也就是说,还是比迂回的方法快。
  这种奇怪的现象怎么解释呢,
我懒得去研读Encode模块的实现了,只先这么推测吧:
  gbk的解码比utf-8要容易得多,所以参数为gbk时的decode方法很快,而参数为utf-8就很慢了。
为什么直接用decode_utf8就这么快呢(比encode用gbk参数还快),只能说,perl对它内置的东西还是做了相当的优化,效率并不低。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-378793-1-1.html 上篇帖子: 神奇的Perl-第六个任务(6) 下篇帖子: 清空.svn目录的Perl脚本
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表