加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl中字符串编码分析和注意事项

发布时间:2020-12-15 23:39:02 所属栏目:大数据 来源:网络整理
导读:在 Perl看来,字符串只有两种形式. 一种是octets,即8位序列,也就是我们通常说的字节数组. 另一种utf8编码的字符串,perl管它叫string. 也就是说: Perl只熟悉两种编码: Ascii(octets)和utf8(string). perl内部字符串由 flag标志位和数据区 两部分组成,其存储结

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

perl内部字符串由flag标志位和数据区两部分组成,其存储结构如下:

这里写图片描述

  1. 假如utf8 flag是On perl就会把数据区内容当成utf8字符串来处理;
  2. 假如utf8 flag是Off,perl就会把数据区内容当成octets来处理. 即字节来处理;

所有字符串相关的函数包括正则表达式、文件检测、都会受utf8 flag的影响。在默认情况下,utf8 flag标志位是off状态,当我们在代码中使用了 use utf8 ,则代表flag标志位是on状态,在当前词法范围内都是有效的。

Encode中的is_utf8函数可以用于检测当前flag开启情况,1代表on 0代表off;以下代码均是使用notepad++进行编码,字符编码格式选择UTF-8格式。


编码格式转换

若要进行不同编码之间的转换,可以使用Encode模块中的decode函数和encode函数,这两个函数使用如下

$octets = encode(ENCODING,STRING);
将标量字符串STRING从perl内部格式编码成ENCODING格式,并且返回字节流序列。

For example,to convert a string from Perl's internal format into ISO-8859-1:
$octets = encode("iso-8859-1",$string);

$string = decode(ENCODING,OCTETS);
以ENCODING编码格式从字节流中解读字符信息,并转化为perl内部格式编码。

For example,to convert ISO-8859-1 data into a string in Perl's internal format:
$string = decode("iso-8859-1",$octets);

下面展示gbk和utf8之间的相互转码,两种编码格式需要经过perl内部编码格式:

这里写图片描述

若待编码的字符串已经是perl内部编码格式(flag on +utf8编码),则可以直接进行编码或者解码,不需要按照上述的过程进行。

例子1:

use Encode;

#当前关闭
print "utf8 flag is 0ffn" if !Encode::is_utf8($string1);

my $string1 = "你好";//是utf8格式,若不编码屏幕输出乱码
print Encode::encode("gbk",Encode::decode("utf8",$string1)),"n";

#flag是off状态,当作字节来处理,长度为6
print "length:",length($string1),"n";

运行结果:

这里写图片描述

例子2:

print "***********utf8 flag is on***************n";
#此后utf8 flag 为on
use utf8;

my $string2 = "你好";

#当前on
print "utf8 flag is onn" if Encode::is_utf8($string2);

#这里$string2相当于是内部格式了 flag is on and utf8 format
#可以直接编码,不用先解码后编码了
print Encode::encode("gbk",$string2),"n";

#当作string来处理,长度为2
print "length:",length($string2),"nnnn";

运行结果:

这里写图片描述


注意事项

我们在使用perl中的文件测试符-e -s -f或者系统命令copy函数时,均要求这些函数的入参或者变量是gbk编码格式,否则会导致不符合预期的编码结果,举例如下:

我在目录下这个路径下创建了txt文件“E:perl文件夹1log.txt”,不同的编码格式答案是不符合预期的。

例子3:

print "**********file test and system copy attentions**************n";
#文件测试或者调用系统copy函数等函数时 均需要使用gbk编码

my $src1 = "E:perl文件夹1log.txt";
my $src2 = "E:perl文件夹1log.txt";
#$src2字符串flag标志位是on,并且本身是utf8编码,
#因此$src2是perl内部格式,可以转为国标
my $gbk_src = Encode::encode("gbk",$src2);

print "gbk encode:$gbk_srcn";

#文件存在 则打印
if (-e $gbk_src){
    print "it existsn";
}
#文件不存在 则打印
unless (-e $src){
    print "it don't existn";
}

运行结果:

这里写图片描述

字符串来源

为了能够正确的进行字符串编解码, 我们首先要知道字符串本来的编码和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也已经打开.
  3. 从文件读入. 这个毫无疑问,你的文件是什么编码,读进来就是什么编码了. 读进来以后,utf8 flag是off状态.
  4. 抓取网页. 网页是什么编码就是什么编码,utf8 flag是off状态. 网站的编码可以从响应头里或者html

参考入下资料:
http://www.voidcn.com/article/p-wksygwkx-brm.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读