zoukankan      html  css  js  c++  java
  • Perl Unicode 全攻略:

    Perl Unicode 全攻略:
    
    耐心看完本文,相信你今后在unicode处理上不同再有问题:
    
    
    在Perl看来,字符串只有两种形式。一种是octets,即8位序列,也就是我们通常说的字节数组
    
    
    另一种utf8 编码的字符串,perl 管它叫string.
    
    也就是说:Perl 只认识两种编码:ascii(octets) 和utf8 (字符串)
    
    
    utf8 flag:
    
    那么 perl 如何却动一个字符串是octets还是utf8编码的字符串呢?
    
    perl 可没有什么智能,它完全是靠字符串的utf8 flag.
    
    在perl 内部,字符串结构由两部分组成:数据和utf8 flag,比如字符串"中国"在perl内部的存储是这样:
    
    
    utf8 flag     数据
    On            中国
    
    
    如果 utf8 flag 是on的话,perl 就会把中国当成utf8 字符串来处理,
    
    如果 utf8 flag 为off,perl就会把他当成octets来处理。
    
    所有的字符串相关的函数包括正则表达式都会受utf8 flag的影响,让我们来看个例子
    
    [root@jxglapp1 pfwx-master]# cat mojo.pl
    use lib "./lib";
    use mojo::Client;
    use Data::Dumper;
    use Mojolicious::Lite;
    use JSON qw/encode_json decode_json/;  
    use Encode;
    no strict;
    no warnings;
    use JSON; 
    use POSIX;
    use JSON::RPC::Client;
    use Data::Dumper;
    use URI::Escape;
    my $client = mojo::Client->new();
      print Dumper($client);
      get '/api/SMSsendx' => sub {
       my $c = shift;
       my $sourceip=$c->param('sourceip');
       my $message = $c->param('message');
          print "Length==";
          print length($message)."
    "; 
          print "$message is $message
    ";
          sleep 30;
    
      app->start;
    
      [root@jxglapp1 pfwx-master]# vim mojo.pl
    [root@jxglapp1 pfwx-master]# morbo mojo.pl
    Server available at http://127.0.0.1:3000
    $VAR1 = bless( {
                     'client_version' => '1.0'
                   }, 'mojo::Client' );
    [Mon Mar 13 08:23:47 2017] [debug] GET "/api/SMSsendx"
    [Mon Mar 13 08:23:47 2017] [debug] Routing to a callback
    Length==2
    $message is 中国
    $flag===1
    
    
    
    ------------------------------------------------------------
    [oracle@oadb utf-8]$ cat a3.pl 
    use Encode;
    use strict;
    
    my $str = "中国";
    print length($str);
    print "
    ";
    Encode::_utf8_on($str);
    print length($str) . "
    ";
    Encode::_utf8_off($str);
    print length($str) . "
    ";
    [oracle@oadb utf-8]$ perl a3.pl 
    6
    2
    6
    
    
    这里我们使用Encode模块的_utf8_on 函数和_utf8_off 函数来开关字符串"中国"的utf8 flag.
    
    可以看到,utf8 flag打开的时候,"中国"被当成utf8 字符串处理,所以其长度为2.
    
    utf8 flag关闭的时候,"中国"被当成octets(字节数组)处理,出来的长度为6
    
    
    
    在看看正则表达式:
    [oracle@oadb utf-8]$ cat a4.pl 
    use Encode;
    use strict;
    
    my $a = "1中国2";
    
    print "$a is $a
    ";
    print length($a)."
    ";
    
    $a =~ s/W+//g;
    
    print "$a is $a
    ";
    
    [oracle@oadb utf-8]$ perl a4.pl 
    $a is 1中国2
    8
    $a is 12
    [oracle@
    
    [oracle@oadb utf-8]$ cat a4.pl 
    use Encode;
    use strict;
    
    my $a = "1中国2";
    Encode::_utf8_off($a);
    
    print "$a is $a
    ";
    print length($a)."
    ";
    
    $a =~ s/W+//g;
    
    print "$a is $a
    ";
    
    [oracle@oadb utf-8]$ perl a4.pl 
    $a is 1中国2
    8
    $a is 12
    
    
    [oracle@oadb utf-8]$ cat a4.pl 
    use Encode;
    use strict;
    
    my $a = "1中国2";
    Encode::_utf8_on($a);
    
    print "$a is $a
    ";
    print length($a)."
    ";
    
    $a =~ s/W+//g;
    
    print "$a is $a
    ";
    
    [oracle@oadb utf-8]$ perl a4.pl 
    Wide character in print at a4.pl line 7.
    $a is 1中国2
    4
    Wide character in print at a4.pl line 12.
    $a is 1中国2
    
    此时匹配不到:
    
    
    
    
    
    
    
    
    
    
    如何确定一个字符串的utf8 flag 是否开启?使用Encode::is_utf8($str)
    
    
    这个函数并不是用来检测一个字符串是不是utf8 编码,而是仅仅看看它的utf8 flag是否开启
    
    [oracle@oadb utf-8]$ cat a4.pl 
    use Encode;
    use strict;
    
    my $a = "1中国2";
    #Encode::_utf8_on($a);
    
    print "$a is $a
    ";
    print length($a)."
    ";
    
    $a =~ s/W+//g;
    
    print "$a is $a
    ";
    
    my $flag=Encode::is_utf8($a);
    print "$flag is $flag
    ";
    [oracle@oadb utf-8]$ perl a4.pl
    $a is 1中国2
    8
    $a is 12
    $flag is
    
    
    [oracle@oadb utf-8]$ cat a4.pl 
    use Encode;
    use strict;
    
    my $a = "1中国2";
    Encode::_utf8_on($a);
    
    print "$a is $a
    ";
    print length($a)."
    ";
    
    $a =~ s/W+//g;
    
    print "$a is $a
    ";
    
    my $flag=Encode::is_utf8($a);
    print "$flag is $flag
    ";
    [oracle@oadb utf-8]$ perl a4.pl 
    Wide character in print at a4.pl line 7.
    $a is 1中国2
    4
    Wide character in print at a4.pl line 12.
    $a is 1中国2
    $flag is 1
    
    unicode 转码:
    
    如果你有一个字符串"中国",它是gb2312编码的。如果它的utf-8 flag是关闭的,
    
    它就会被当成octets来处理,length()会返回4,这通常不是你想要的。
    
    而 如果你开启它的utf8 flag,则它会被当做utf8 编码的字符串来处理。
    
    
    由于它本来的编码是gb2312的,不是utf-8的,这就可能导致错误发生。
    
    
    解决的方法很显然,如果你的字符串本来不是utf8编码的,应该先把它转成utf8编码,并且
    
    使它的utf8 flag处于开启状态。对于一个gb2312编码的字符串,你可以使用:
    
    
    程序代码:
    $str = Encode::decode("gb2312", $str);
    
    
    字符串连接:
    
    . 是字符串连接操作符,连接两个字符串时,如果两个字符串的utf8 flag都是off,
    
    那么结果字符串也是off。
    
    如果其中任何一个字符串的utf8 flag是on的话,那么结果字符串的utf8 flag将是on.
    
    
    perl unicode编程基本原则
    
    对于任何要处理的unicode 字符串, 1)把它的编码转换成utf8 
    
    2) 开启它的utf8 flag
    
    
    字符串来源:
    
    为了应用上面说到的基本原则,我们首选要知道字符串本来的编码和utf8 flag开关情况,这里我们讨论几种情况:
    
    1) 命令行参数和标准输入。 
    从命令行参数或标准输入(STDIN)来的字符串, 它的编码跟locale有关。
     如果你的locale是zh_CN或zh_CN.gb2312, 那么进来的字符串就是gb2312编码,
     如果你的locale是zh_CN.gbk, 那么进来的编码就是gbk, 如果你的编码是zh_CN.UTF8, 那进来的编码就是utf8。
     不管是什么编码, 进来的字符串的utf8 flag都是关闭的状态。
    
    2)
    
    你的源代码里的字符串。 
    
    
    这要看你编写源代码用的是什么编码,在editplus里, 你可以通过“文件”->“另存为”查看和更改编码。 在linux下, 你可以cat一个源代码文件, 如果中文正常显示, 说明源代码的编码跟locale是一致的。源代码里的字符串的utf8 flag同样是关闭的状态。
    
    
    如果你的源代码里含有中文, 那么你最好遵循这个原则: 1) 编写代码时使用utf8编码, 2)在文件的开头加上“use utf8;”语句。这样, 你源代码里的字符串就都会是utf8编码的, 并且utf8 flag也已经打开。
    

  • 相关阅读:
    网络English word
    Top instruction significance and use sar command
    远程传输+用yum安装文件+make编译安装软件
    windows主机向虚拟机Linux传输过程的错误重重艰苦历程
    pair结构体数组
    set容器
    scanf多组样例输入
    贪心硬币
    补一下蛇形矩阵
    如何在eclipse运行asn
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13349822.html
Copyright © 2011-2022 走看看