Perl匹配中文

來源:互聯網
上載者:User

轉載:http://blog.csdn.net/jallin2001/archive/2009/11/13/4808618.aspx

 

大家經常使用Regex的字元集從字串中抽取或排除中文字元,但是這樣做很費事,效果也並不是很理想。實際上Perl從5.6開始已經開始在內部使用 utf8編碼來表示字元,也就是說對中文以及其他語言字元的處理應該是完全沒有問題的。關鍵在於目前使用的編輯器以及檔案格式並不都能很好地支援 utf8,委屈了Perl的強大能力。實際上我們只需要利用好Encode這個模組便能充分發揮Perl的utf8字元的優勢了。

下面就以中文文本的處理為例進行說明(注意:編輯下面這段程式不能用使用utf8編碼的編輯器),比如有一個字串"測試文本",我們想要把這個中文字串拆成單個字元,可以這樣寫:
use Encode;
use Encode::CN; #可寫可不寫
$dat="測試文本";
$str=decode("gb2312",$dat);
@chars=split //,$str;
foreach $char (@chars) {
print encode("gb2312",$char),"/n";
}
結果大家試一試就知道了,應該是令人滿意的。

這裡主要用到了Encode模組的decode、encode函數。要瞭解這兩個函數的作用我們需要清楚幾個概念:
1、Perl字串是使用utf8編碼的,它由Unicode字元組成而不是單個位元組,每個utf8編碼的Unicode字元佔1~4個位元組(變長)。
2、進入或離開Perl處理環境(比如輸出到螢幕、讀入和儲存檔案等等)時不是直接使用Perl字串,而需要把Perl字串轉換成位元組流,轉換過程中使用何種編碼方式完全取決於你(或者由Perl代勞)。一旦Perl字串向位元組流的編碼完成,字元的概念就不存在了,變成了純粹的位元組組合,如何解釋這些組合則是你自己的工作。

我們可以看出如果想要Perl按照我們的字元概念來對待文本,文本資料就需要一直用Perl字串的形式存放。但是我們平時寫出的每個字元一般都被作為純 ASCII字元儲存(包括在程式中明文寫出的字串),也就是位元組流的形式,這裡就需要encode和decode函數的協助了。

encode函數顧名思義是用來編碼Perl字串的。它將Perl字串中的字元用指定的編碼格式編碼,最終轉化為位元組流的形式,因此和Perl處理環境之外的事物打交道經常需要它。其格式很簡單:
$octets = encode(ENCODING, $string [, CHECK])
這裡$string是Perl字串,ENCODING是給定的編碼方式,$octets則是編碼之後的位元組流,CHECK表示轉換時如何處理畸變字元(也就是Perl認不出來的字元)。一般不需要使用CHECK,讓Perl按預設規則處理即可。
編碼方式視語言環境的不同有很大變化,預設可以識別utf8、ascii、ascii-ctrl、iso-8859-1等,中文環境(CN)增加了 euc-cn(gb2312與之等價)、cp936(gbk與之等價)、hz等,還有日文環境(JP)、韓文(KR)等等,在此不一一盡數。

decode函數則是用來解碼位元組流的。它按照你給出的編碼格式解釋給定的位元組流,將其轉化為使用utf8編碼的Perl字串,一般來說從終端或者檔案取得的文本資料都應該用decode轉換為Perl字串的形式。它的格式為:
$string = decode(ENCODING, $octets [, CHECK])
$string、ENCODING、$octets和CHECK的含義同上。

現在就很容易理解上面寫的那段程式了。因為字串是用明文寫出的,存放的時候已經是位元組流形式,喪失了本來的意義,所以首先就要用decode函數將其轉換為Perl字串,由於漢字一般都用gb2312格式編碼,這裡decode也要使用gb2312編碼格式。轉換完成後Perl對待字元的行為就和我們一樣了,平時對字串進行操作的函數基本上都能正確對字元進行處理,除了那些本來就把字串當成一堆位元組的函數(如vec、pack、unpack 等)。於是split就能把字串切成單個字元了。最後由於在輸出的時候不能直接使用utf8編碼的字串,還需要將切割後的字元用encode函數編碼為 gb2312格式的位元組流,再用print輸出。

Encode模組的初步應用大概就是這樣,詳細情況還是要參閱模組的文檔。實際上如果我們使用UltraEditor等等支援編輯utf8編碼檔案的編輯器寫程式,基本上用不著Encode模組,在程式開頭加上一句use utf8就行。這時Perl預設包括程式本身在內的所有的字元都是Unicode字元,可以隨便使用Unicode範圍內的字元,甚至可以用非英文字元作為標識符,只是輸出的時候可能還需要用Encode模組。比如用UE的utf8編碼模式編輯這個程式:
use utf8;
$單價=10;
$數量=100;
$總額=$單價*$數量;
print "$總額/n";
可以在Perl 5.6以後的版本中正常運行並給出結果,是不是很爽?:) 這種模式最大的優點就是在字串中可以混合多種語言的文字,就算中日韓英加上阿拉伯字元都在一個字串中出現也沒問題;不像使用Encode模組那樣必須固定一種編碼方式,中日韓英字元同時出現還好辦,因為gbk包含了所有這些字元,可是再加上一些非亞洲語言字元就不一定能處理了。所以以後用 Unicode編碼應該是大勢所趨。

希望寫的這些能對大家有所協助。

發信人: chaoslawful (Skeleton Warrior), 信區: Perl
標 題: 對Perl處理中文字元的一點補充
發信站: BBS 水木清華站 (Thu Oct 30 09:45:23 2003), 轉信

從Perl5.8開始的版本除了使用Encode模組將中文字元轉換成utf8字元以外,還可以使用use encoding指示符來更方便地處理。如下所示

use encoding 'gbk';
$str="你好";
print length($str)."/n";
@chars=split //,$str;
print "@chars/n";

還可以指定輸入輸出使用不同的編碼方式,達到轉換編碼的目的
use encoding 'gbk',STDOUT=>'utf8'; # 輸入用gbk編碼,輸出用utf8編碼
或者
use encoding 'gbk',STDIN=>'utf8'; # 輸入用utf8編碼,輸出用gbk編碼

如果想用漢字作變數名,達到和use utf8指示符相同的效果,可以這樣寫

use encoding 'gbk',Filter=>1;
$變數=10;
print "$變數/n";

不過這樣會降低相容性,所以不推薦使用。更詳細的描述可參考perldoc encoding

有時候要考慮字元編碼的特性,比如你找到亂碼, 如"闈炲尰鍔′漢鍛?","鍖誨姟浜哄憳"分別表示"非醫務人員"和"醫務人員",所以你的Regex可以寫為:

$_ =~ /闈炲尰鍔′漢鍛/用來匹配文本中包含非醫務人員的檔案。

當然編譯器預設是GBK,我的文字檔是UTF-8無ROM格式.

你通過.*直接輸出就可以進行匹配了。

 

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/jallin2001/archive/2009/11/13/4808618.aspx

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.