第三章 Perl语言(二)-值

变量值

新手程序员往往只关注自己的程序要做些什么,而成熟的程序员则是在想如何为程序设计一个合适的数据模型。****变量帮你对数据进行抽象,变量的值就是让程序变得具体从而发挥实际作用。****变量的值可以是你期望的任何东西,比如名字、地址、家和学校的距离、你去年的花费。在程序中,对数据的格式要求往往非常严格。程序员需要有效的方法(简单,快速,高效)来表示他们的数据。

字符串

字符串就是一连串的字符(可以是文本也可以说是二进制数据)。比如它可以是你的名字,也可以是一个图片文件的内容,或者程序本身源代码。

在程序中,要表示一个字符串时,你需要将它们包围起来,最常见的就是使用单引号或双引号将它们包围起来:

my $name = 'Donner Odinson, Bringer of Despair';
my $address = "Room 539, Bilskirnir, Valhalla";

单引号包围的字符表示的意思就是****字面本身****,双引号包围的字符则****还可能具有非字面本身的意义(内插/转义)****。

单引号的使用有2个例外:要表示单引号自身时需要在前面加反斜杠;要表现反斜杠时也需要在前面加反斜杠:

'Don\'t forget to escape'    #Don't forget to escape
'Modern \\ Perl'    #Modern \ Perl
'backslash, not a quote: \\'    #backslash, not a quote:\

双引号包围的字符则拥有更强的魔法,如支持更多反斜杠转义:

"\t"
"\n"
"\f"
"\b"

它们分别表示制表、换行、换页、退格。

当然对于双引号包围的普通字符意思不会变,仅仅表示这些是字符串字面本身。
如果要连接字符串,可以使用点号操作符(.):

my $kitten = 'Choco' . ' ' . 'Spidermonkey';
my $kitten = "Choco" . " " . "Spidermonkey";

你也可以在双引号中放入变量,那么变量的当前内容就会成为字符串的一部分,就好像把他们连接在一起:

my $factoid = "$name lives at $address!";
my $factoid = $name . ' lives at ' . $address . '!';

如果要表示双引号本身要在前面加反斜杠转义:

my $quote = "\"Ouch,\", he cried. \"That hurt!\"";    #"Ouch,", he cried. "That hurt!"

上面这个例子反斜杠有点多,看起来乱糟糟的。所以Perl里还提供了操作符(q)和操作符(qq)来让这种情况变得简单。
q 操作符的效果就像单引号,不会内插;qq操作符类似双引号,会内插。
它们都需要定界符。定界符可以是2个相同的符号,也可以是成对的符号。
挑选合适的定界符可以避免上面例子中的反斜杠:

my $quote = qq{"Ouch", he said. "That hurt!"};
my $reminder = q^Don't escape the single quote!^;
my $complaint = q{It's too early to be awake.};

当你需要声明一个复杂的字符串时,可以是用heredoc语法:

my $blurb =<<'END_BLURB';
He looked up. "Change is the constant on which they all
can agree. We instead, born out of time, remain perfect
and perfectly self-aware. We only suffer change as we
pursue it. It is against our nature. We rebel against
that change. Shall we consider them greater for it?"
END_BLURB

这里<<'END_BLURB'语法有3部分。二个小于号标志着这里是heredoc语法。用单引号引起表示这段字符串不做内插(类似单引号的行为,且无例外–单引号反斜杠都原样保留)。如果没有使用单引号引起默认就是双引号的行为(支持内插)。END_BLURB就是结束定界符。****注意结尾定界符必须要在那一行的行首!****

sub some_function {
     my $ingredients =<<'END_INGREDIENTS';
     Two eggs
     One cup flour
     Two ounces butter
     One-quarter teaspoon salt
     One cup milk
     One drop vanilla
     Season to taste
END_INGREDIENTS
}

Unicode和字符串

Unicode是一个用来表示世界上所有文字的字符系统。相对的就是纯英文字符,英文字符集只有127个字符,只需要8个比特位就够用了。这2种类型字符集都被广泛使用,Perl的字符串对2种类型都支持。

Unicode字符序列
每一个字符都有一个码点,这是该字符在Unicode字符集当中的唯一标识。

Octet序列(八位序列)
通常说的2进制数据就是8位序列,一个8比特位的数字,可以表示0到255。

为什么叫Octet序列而不是叫字节?不同的计算机对字节的定义不一样,而Octet则总是表示8个比特位。

****Perl默认将所有的输入数据都视为八位序列。****

字符编码

****文件句柄中使用Unicode编码****
如果你知道该以什么样的编码方式处理文件,那就可以在IO层进行指定,Perl会自动做相应的转换。如以UTF-8的编码方式读取文件:

open my $fh, '<:utf8', $textfile;
my $unicode_string = <$fh>;

对于已经打开了的文件句柄,则可以使用binmode方法:

binmode $fh, ':utf8';
my $unicode_string = <$fh>;
binmode STDOUT, ':utf8';
say $unicode_string;

想要方便的在所有地方都启用UTF-8,可以试试utf8::all模块。

****在数据中使用Unicode编码****
系统模块Encode提供了各种各样的编码转换功能。

my $from_utf8 = decode('utf8', $data);    #对$data进行UTF-8解码
my $to_latin1 = encode('iso-8859-1', $string);    #对$string进行拉丁解码

读取的数据时进行正确的解码,输出数据时进行正确的编码,能避免所有编码方面的问题。

****在源代码中使用Unicode编码****
启用utf8后就可以在代码中使用UTF-8字符了:

use utf8;
sub £_to_¥ { ... }
my $yen = £_to_¥('1000£');

这样写代码的前提条件是你的编辑器支持UTF-8,并且能将代码文件以正确的编码方式保存。

在双引号包围的字符串中,你可以使用\x{}语法来表示Unicode字符:

my $escaped_thorn = "\x{00FE}";

有些Unicode字符是有名字的,启用charnames后,可以使用\N{}语法用名字来表示:

use charnames ':full';

my $escaped_thorn = "\x{00FE}";
my $named_thorn = "\N{LATIN SMALL LETTER THORN}";

****隐式转换****
当你将多种字符集混合使用并且没有指明时,Perl会自动对字符串进行编码转换,这有可能导致出现非常隐秘的问题,所以不要这样做!

如果你的工作内容是处理Unicode,请使用Perl 5.16以上的版本,并且总是遵循这样一个原则:读取的数据时进行正确的解码,输出数据时进行正确的编码。

关于Perl与Unicode的更多细节请阅读:http://www.perl.com/pub/2012/04/perlunicook-standard-preamble.html

数字

Perl支持整型数字和浮点数字,你可以使用不同的方式来表示它们,二进制、八进制、十进制、十六进制:

my $integer = 42;    #整型
my $float = 0.007;    #浮点型
my $sci_float = 1.02e14;    #科学计数法,浮点数
my $binary = 0b101010;    #二进制0b前缀
my $octal = 052;    #十六进制0前缀
my $hex = 0x20;    #十六进制0x前缀

还可以使用下划线来增加可读性:(注意不是逗号,因为逗号在Perl中有特殊意义)

my $billion = 1000000000;
my $billion = 1_000_000_000;
my $billion = 10_0_00_00_0_0_0;

罕见的情况下你可能会有数字和字符相互转换的困扰,这时可以看看系统模块Scalar::Util( looks_like_number函数)。
如果你需要识别数字类型(如整型数字、浮点型数字),可以试试Regexp::Common模块(CPAN)。

Undef

Perl里的undef表示一个未分配、不确定、未知的值。
一个声明了但是没有定义的标量值就是undef:

my $name = undef;     # unnecessary assignment
my $rank;     # also contains undef

在布尔语境中,undef等效于假值。在字符串语境中内插undef值的变量将会产生一个警告:

my $undefined;
my $defined = $undefined . '... and so forth';

#Use of uninitialized value $undefined in concatenation (.) or string...

使用defined来测试undef值将返回假;测试undef外的其他任何值都返回真。

my $status = 'suffering from a cold';
say defined $status;     # 1, which is a true value
say defined undef;     # empty string; a false value

空列表

在赋值右边,使用一对小括号就表示一个空列表。
在标量语境中,空列表等价于undef;在列表语境中,就是一个空的列表。
当在赋值左边时,()强制为列表语境:

my $count = () = get_clown_hats();

首先空列表强制为列表语境,所以会在列表语境中调用get_clown_hats(),函数会返回一系列的值(列表)。然后赋值给空列表,空列表会将所有的值都丢弃,列表赋值这个操作又是在标量上下文,所以结果就会将返回元素的个数。现在看起来可能有点绕,但随着Perl技能的提高,你会越来越觉得自然。

列表

一个用逗号分隔的单个或多个表达式组就是一个列表。
可以作为值来使用:

my @first_fibs = (1, 1, 2, 3, 5, 8, 13, 21);

也可以用于被赋值:

my ($package, $filename, $line) = caller();

作为表达式列表:

say name(), ' => ', age();

****注意:列表不是由圆括号创建的,是由逗号创建的。****

使用范围操作符(..)可以很方便的创建列表:

my @chars = 'a' .. 'z';
my @count = 13 .. 27;

可以使用qw()操作符分隔空白来产生字符串列表:

my @stooges = qw( Larry Curly Moe Shemp Joey Kenny );

在qw()操作符中如果存在注释符号和逗号会产生警告,因为这种情况极有可能是你不小心写错了。

列表和数组相似,但他们不能互换。列表是值,而数组是容器。

    原文作者:可以没名字吗
    原文地址: https://www.jianshu.com/p/a46452415a6f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞