perl中utf-8編碼的處理

來源:互聯網
上載者:User

為了比較方便,考慮這樣一個應用:把html頁面中的所有非漢字字元全部去掉。

這裡順便告訴大家一個秘訣,只要文本被perl 按正確編碼解釋後,利用/w就可以匹配一個字母、數字、_、漢字,這個特性是不是很方便,所以我們只要用如下兩次Regex就可以去掉所有非漢字字元,包括全形的一些標點(@#$%<,())也能去的很乾淨:
$str =~ s/[^w]//g;
$str =~ s/[0-9a-zA-Z_]//g;
問題在於如何讓perl正確的理解我們的文本,我先給出我們的測試程式如下:
#! /usr/bin/perl 

use strict;use Encode;use open IN => ":raw",   OUT => ":raw";my $arg = $ARGV[0];sub aaa {        open FH, "testutf8" or die "aaa$! ";        local $/ = undef;        binmode FH, ":utf8";        my $str = <FH>;        return $str;}sub bbb {        open FH, "testutf8";        local $/ = undef;        binmode FH, ":raw";        my $str = <FH>;        $str = pack "U0C*", unpack "C*", $str;        return $str;}sub ccc {        open FH, "testutf8" or die "aaa$! ";        local $/ = undef;        binmode FH, ":raw";        my $str = <FH>;        $str = Encode::decode_utf8($str);        return $str;          }sub ddd {        open FH, "testutf8" or die "aaa$! ";        local $/ = undef;             binmode FH, ":raw";           my $str = <FH>;               $str = decode('utf-8', $str);          return $str;}sub eee {        open FH, "testgb" or die "aaa$! ";        local $/ = undef;        binmode FH, ":raw";        my $str = <FH>;        Encode::from_to($str, 'gbk', 'utf-8');        $str = Encode::decode_utf8($str);        return $str;}sub fff {        my $str = `iconv -f gbk -t utf-8 testgb`;        $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對它內建的東西還是做了相當的最佳化,效率並不低。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.