您的位置:首页 > 其它

perl让人纠结的几个问题

2015-12-28 20:34 211 查看
编码格式问题:

编码格式:(Perl Unicode全攻略)http://blog.csdn.net/zhangxinrun/article/details/6409846

编码格式转换:http://blog.csdn.net/sptoor/article/details/5201588

gb2312 gbk unicode utf-8等编码解析:http://www.blogjava.net/NeonWay/archive/2007/01/29/96437.html

这里主要用到了Encode模块的decode、encode函数。要了解这两个函数的作用我们需要清楚几个概念:

1、Perl字符串是使用utf8编码的,它由Unicode字符组成而不是单个字节,每个utf8编码的Unicode字符占1~4个字节(变长)。

2、进入或离开Perl处理环境(比如输出到屏幕、读入和保存文件等等)时不是直接使用Perl字符串,而需要把Perl字符串转换成字节流,转换过程中使用何种编码方式完全取决于你(或者由Perl代劳)。一旦Perl字符串向字节流的编码完成,字符的概念就不存在了,变成了纯粹的字节组合,如何解释这些组合则是你自己的工作。

encode函数顾名思义是用来编码Perl字符串的。它将Perl字符串中的字符用指定的编码格式编码,最终转化为字节流的形式,因此和Perl处理环境之外的事物打交道经常需要它。其格式很简单:

$octets = encode(ENCODING, $string [, CHECK])

$string:  Perl字符串

encoding: 是给定的编码方式

$octets:  是编码之后的字节流

check:   表示转换时如何处理畸变字符(也就是Perl认不出来的字符)。一般不需使用

编码方式视语言环境的不同有很大变化,默认可以识别utf8、ascii、ascii-ctrl、iso-8859-1等。

说明:

1)除上面几种默认的,perl中编码方式还可以取:gbk、gbk2312、utf8、utf16、utf16le、ucs-2等。

2)利用decode与encode可以实现不同编码方式的转换,但不是直接转换,中间可能会做一些简单的处理。如gbk->uft16le,

对换行符号要转换0A00->0D000A00,中间可能会用到unpack/pack及其对文件进行二进制读写的操作。

3)perl正则表达式,应该utf8格式下进行。对gbk虽然一般情况下可以正常匹配,但特殊时会遇到“代码页”的问题:即第n个汉字的第二个字节和第n+1汉字的第一字节加入正好匹配另一个中文,被替换,则会造成乱码。utf8无此问题。

4)输出到某种编码格式(如“gbk”)的文件: print PF_OUT encode("gbk",decode("uft16",$data));  #从utf16文件到gbk文件,且无论是否binmode输出文件PF_OUT 。

 

decode函数则是用来解码字节流的。它按照你给出的编码格式解释给定的字节流,将其转化为使用utf8编码的Perl字符串,一般来说从终端或者文件取得的文本数据都应该用decode转换为Perl字符串的形式。它的格式为:

$string = decode(ENCODING, $octets [, CHECK])

$string、ENCODING、$octets和CHECK的含义同上。

UNICODE <-> ASCII:

http://soft.zdnet.com.cn/software_zone/2002/0226/44356.shtml

sub MakeUNICODE {

   my ($d) = @_;

   $d =~ s/(.)/$1\x00/g;

   return $d;

  }

  sub MakeASCII {

   my ($d) = @_;

   $d =~ s/(.)x00/$1/g;

   return $d;

  }

注意:只有前面的255个UNICODE字符可以映射ASCII字符表,所以许多UNICODE字符是不能转换的。

utf8->unicode:http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=1714677&page=1#pid12263755

sub Utf8ToUnicode()

{

    my($uft8Str)=@_;

    my $unicodeStr;

#my $bom_big_endian = pack("n", 0xfeff);

#my $unicode_str_big_endian = encode("UCS-2", $uft8Str);

#$unicodeStr = $bom_big_endian.$unicode_str_big_endian;

my $bom_little_endian = pack("n", 0xfffe);

my $unicode_str_little_endian = pack("n*", unpack("v*", encode("UCS-2", $uft8Str)));

$unicodeStr = $bom_little_endian.$unicode_str_little_endian;

return $unicodeStr;

}

perl子程序传递、返回多个数组问题:

http://zhidao.baidu.com/question/343423708.html

#输入传递多数组,且返回多数组实例(以数组引用实现):

sub choose()

{

    my ($pArr1, $pArr2, $pArr3)=@_;

    ....... #子程序内,使用@$pArr1作为数组;

    

    my (@a1,@a2,@a3);

    return (\@a1,\@a2,\@a3);  #返回数组的引用

}

my (@a1,@a2,@a3);

my (@r1,@r2,@r3);

my @refs= &choose(\@a1,\@a2,\@a3); #调用时,传递数组的引用;以一个数组来接收返回值(元素为数组的引用)。

@r1 = @{$refs[0]};

@r2 = @{$refs[1]};

@r3 = @{$refs[2]};

说明:

1.首先perl中只能对简单的列表赋值给变量列表,而不能将列表赋值给,列表组成的列表。

比如@arr = (1,2,3);这个是可以的,($a,$b) = ($b, $a);这个也对, 但是(@arr1, @arr2) = (@arr2, @arr1); 这个就错了,原因在于perl的列表是贪婪的, 也就是说 @arr1会尽可能的接受后面的数据,而(@arr2,@arr1)本身就是一个大的列表, 就全部被@arr1接受了,而@arr2为空。这个结论,同样适用于哈希数组(关联数组)。

但是,如果只有一个数组,并且将数组置于列表的最后一个元素,如($a,@arr)=($b,@arrb);是可以得到预期结果的。利用这一点,当只需要传递一个数组时,也可以my($param1,...,@arr)=@_;的形式来传递数组。当然,传递数组引用的方法是普遍适用的。

2.唯一的办法就是以数组引用形式来传递数据。所以($ref_a1, $ref_a2) = (\@a1, \@a2);这种形式是可以的。

使用时可以还原引用,如 @{$ref_a1},或者直接读下标,$ref_a1->
.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  脚本 perl