autodataming的个人博客分享 http://blog.sciencenet.cn/u/autodataming

博文

perl 编码utf8 utf-8 gbk中文英文正则匹配

已有 4835 次阅读 2014-10-13 19:18 |个人分类:系统|系统分类:科研笔记

背景:

别人用Win32::GUI 写了一个图形界面,其中要处理中文英文,中文乱码或者不匹配。

以前都是到网上随便搞个代码,能用就行,不是很了解其中的原理。

答应了帮助别人,就到网上查了所有的资料,

特别感谢 许伦大神写的这份文档

Perl_Unicode全攻略.doc


熟读了50遍,终于顿悟。


终结了一套方法:

1首先把所有的输入文件控制成utf-8格式。

2控制你的cmd终端的编码格式,

比如gbk,chcp 936

或者utf-8,chcp 65001

3知道你GUI界面上显示字符的编码



#这些内容时刻记住

Perl看来, 字符串只有两种形式。一种是octets, 8位序列, 也就是我们通常说的字节数组.另一种utf8编码的字符串, perl管它叫string也就是说: Perl只认识两种编码:Ascii(octets)utf8(string)

正则匹配更好的支持utf8,所以我们要把字符串在perl内部都自动转换成utf8编码


怎么判断变量$searchitem2是utf8还是octets?

我又总结一套方法


my $flag;
$flag = utf8::is_utf8($searchitem2); # since Perl 5.8.1
print $flag,"item2ggg\n";
$flag = utf8::valid($searchitem2);
print $flag,"item2vv\n";

如果两个flag都是utf8则为utf8.

print length($searchitem2) . "^^^^^^^^^^\n";  

#如果长度是汉字的个数则为utf8



########################################################




具体方法:

读取GUI中的字符到变量,然后把变量直接输出到cmd,如果显示正常就说明和cmd中的编码一致

#####################################################################################

具体分析参考我的demo.pl

demo.pl


关键代码

###################################

sub searchbutton_Click
{
 
  my $content;
   my $searchitem2 =$Window->textfield2->Text();  #汉  #不是utf8
   my $old=$searchitem2;
  # 这里的3个eval,可以告诉我们GUI中不是什么编码

 
eval {my $str2 = $searchitem2; Encode::decode("gbk", $str2, 1)};
print "not gbk: $@\n" if $@;

eval {my $str2 = $searchitem2; Encode::decode("big5", $str2, 1)};
print "not big5: $@\n" if $@;

eval {my $str2 = $searchitem2; Encode::decode("utf8", $str2, 1)};
print "not utf8: $@\n" if $@;
#知道不是utf-8编码

#然后我们可以把cmd设置成gbk编码,然后把print $searchitem2.可以正常显示,说明GUI中是GBK编码

$searchitem2 = Encode::decode("gbk", $searchitem2);  #解码成utf8



print length($searchitem2) . "^^^^^^^^^^\n";
my $flag;
$flag = utf8::is_utf8($searchitem2); # since Perl 5.8.1
print $flag,"item2ggg\n";
$flag = utf8::valid($searchitem2);
print $flag,"item2vv\n";

       open FH,"<:encoding(UTF-8)","$file" or die "can't know utf-8,please confirm utf-8";
     #open FH,"$file" or die "can't know utf-8,please confirm utf-8";
    while(<FH>)
    {
        #$_= decode("UTF-8", $_);#有些电脑默认是打开utf8的,有些是默认关闭的
        $_=decode_utf8($_);  #打开utf-8的文件会不会自动打开utf8的开关,如果打开就不需要这句话

#如果报错,cannot decode string with wide characters,提示我们重复decode
         $flag = utf8::is_utf8($_); # since Perl 5.8.1
print $flag,"ggggggggg\n";
$flag = utf8::valid($_);
print $flag,"vvvvvvvvvv\n";

#如果这两个$flag 不是1,就说明是关的状态,需要开启。
   
        if($_=~/$searchitem2/)   #if($_=~/汉/)  run ok
         {
            #在显示之前需要把它编码成终端支持的格式
         $content = Encode::encode('gbk', $_);
             $resutobj->{'-text'}.="$content ok\r\n";
           
             
        }
        else
        {

#如果cmd终端是utf-8,可以直接打印utf8的。

#如果cmd终端是gbk,则需要先编码再打印
        print $_;
       
        #$resutobj->{'-text'}.=  "  $old fail\r\n";  #这里可以打印出来,说明是gbk编码
        }
   }
   
}

##########################################################

考虑是不是重复decode了。


Encode::_utf8_on($str); 开启utf8模式,不仅仅是on,需要确保正确解码,

具体转换方法如下

解决的方法很显然, 如果你的字符串本来不是utf8编码的, 应该先把它转成utf8编码, 并且使它的utf8 flag处于开启状态。

1

对于一个gb2312编码的字符串, 你可以使用

程序代码:

 

$str = Encode::decode("gb2312",$str);

 

来将其转化为utf8编码并开启utf8 flag

2

 

如果你的字符串编码本来就是utf8,只是utf8 flag没有打开, 那么你可以使用以下三种方式中的任一种来开启utf8 flag:

 

程序代码:

 

$str = Encode::decode_utf8($str);

$str = Encode::decode("utf8",$str);

Encode::_utf8_on($str);

###########################################################


更多 精彩:  http://blog.sciencenet.cn/home.php?mod=space&uid=950202


###########################################################

 

最好还有1点要注意

utf8不是utf-8

utf8是perl独特的编码,虽然和utf-8很像(可以在编码为utf-8的终端直接输出utf8的编码的内容)。

所以都要转成utf8,才能让perl处理。

$str 是utf-8编码的。需要转utf8,这样perl正则处理才好。

$str = Encode::decode_utf8($str);


好像显示乱码:

可以看我的word,

perl 编码.docx







http://blog.sciencenet.cn/blog-950202-835391.html

上一篇:adf out文件中的能量解读
下一篇:解决SCF不收敛问题的方法---XQC关键词的重要性

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备14006957 )

GMT+8, 2020-1-19 13:11

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部