第三章 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()操作符中如果存在注释符号和逗号会产生警告,因为这种情况极有可能是你不小心写错了。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容

  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,204评论 0 4
  • 从匹配中返回值 Match 对象 成功的匹配总是返回一个 Match 对象, 这个对象通常也被放进 $/ 中, (...
    焉知非鱼阅读 1,772评论 0 1
  • 有心的朋友可能注意到了,一部日本的动漫电影火遍了我们的生活,到处可以见到与它相关的东西,比如朋友圈刷屏、手机壁纸、...
    简意梵阅读 338评论 2 3
  • 乡村的夜晚 是上帝的施舍,老天的馈赠 久违了的父老乡亲 在这日渐临近的端午佳节 窗外,日头正毒 我失去了乡土,自然...
    碧海青天2017阅读 533评论 0 0
  • “不回去?”历川疑惑道。 徐中听见声音转过身来。 “蹭车咯。”徐中朝他弯着嘴角。 “小鬼头倒是挺会占便宜的。”历川...
    哒哒哒5678阅读 335评论 0 0