Scalar变量

    一个scalar变量能包含:

    • undef(对应Python中的None、PHP中的null
    • 数值(Perl不区分整形和浮点类型)
    • 字符串
    • 其他变量的引用。
    1. my $num = 4040.5;
    2. print $num; # "4040.5"
    1. my $string = "world";
    2. print $string; # "world"

    (稍后会详细说明“引用”。)

    .运算符进行字符串连接(与PHP一样):

    1. print "Hello ".$string; # "Hello world"

    “布尔类型”(“Boolean”)

    Perl没有内置的布尔类型。if语句中的scalar变量仅在以下情况下被认为是“false”:

    • undef
    • 数值0
    • 字符串""
    • 字符串"0"

    Perl的文档中反复强调函数在某些情况下返回“true”或者“false”。实际上,当一个函数声称它返回“true”,返回值往往是1,而当一个函数声称它返回“false”,返回值往往是一个空字符串""

    弱类型

    无法判定一个scalar包含的是一个数值还是字符串。更准确的来说,我们没有必要知道这个信息。一个scalar按照数值还是字符串的方式参与运算,是完全取决于运算符的。因此,像字符串一样使用的时候,scalar就按字符串的方式参与运算,而像数值一样使用的时候,scalar就按照数值的方式参与运算(如果无法转换成数值则会抛出一个警告):

    1. my $str1 = "4G";
    2. my $str2 = "4H";
    3. print $str1 . $str2; # "4G4H"
    4. print $str1 + $str2; # "8" 并且抛出两个警告
    5. print $str1 eq $str2; # "" (空字符串,也就是false)
    6. print $str1 == $str2; # "1" 并且抛出两个警告
    7. # 经典错误
    8. print "yes" == "no"; # "1" 并且抛出两个警告,按数值方式参与运算,两边求值结果都是0

    教训是应该总是在恰当的情况下使用正确的运算符,对于比较数值和字符串有两套不同的运算符:

    1. # 数值运算符: <, >, <=, >=, ==, !=, <=>, +, *
    2. # 字符串运算符: lt, gt, le, ge, eq, ne, cmp, ., x

    Array变量

    Array变量是包含一个scalar列表的、由从0开始的整形数为下标存取的变量。在Python里被称为list,而在PHP里被称为array。数组可以用一个圆括号包围的scalar列表来声明(译者注:原文declaration,而这里实际表达的含义应为“初始化”,而不是对于变量标识符的声明,下同):

    1. my @array = (
    2. "print",
    3. "these",
    4. "strings",
    5. "out",
    6. "for",
    7. "me", # 末尾多余的逗号语法上是允许的

    你必须要使用美元符号来存取array中的值,因为取到的值是一个scalar而非array:

    1. print $array[0]; # "print"
    2. print $array[1]; # "these"
    3. print $array[2]; # "strings"
    4. print $array[3]; # "out"
    5. print $array[4]; # "for"
    6. print $array[6]; # 返回undef,打印""并且抛出一个警告

    同时存在scalar变量$var和包含scalar元素$var[0]的array变量@var是没有冲突的,不过会对代码的读者造成一些误导,所以请避免这种情况。

    取得array的长度

    1. print "This array has ".(scalar @array)."elements"; # "This array has 6 elements"
    2. print "The last populated index is ".$#array; # "The last populated index is 5"

    调用Perl脚本时使用的参数列表被保存在@ARGV中。

    变量可以被插入到字符串中被求值:

    1. print "Hello $string"; # "Hello world"
    2. print "@array"; # "print these strings out for me"

    小心。也许有一点你会把某个人的email地址放在一个字符串里,比如"jeff@gmail.com"。Perl会去尝试找一个名叫@gmail的array变量,求值并插入到字符串中,如果没有找到这个变量,将会导致一个运行时错误。有两种方法可以避免对字符串中的变量名求值:用反斜杠对@进行转义,或者将双引号改为单引号。

    1. print "Hello \$string"; # "Hello $string"
    2. print 'Hello $string'; # "Hello $string"
    3. print "\@array"; # "@array"
    4. print '@array'; # "@array"

    Hash变量

    Hash变量是包含一个scalar列表的、由字符串为下标存取的变量。在Python中被称为dictionary,而在PHP中被称为array

    1. my %scientists = (
    2. "Newton" => "Isaac",
    3. "Einstein" => "Albert",
    4. "Darwin" => "Charles",
    5. );

    请注意这个声明与array何其相似。事实上,这个双箭头符号=>被称为“fat comma”(胖逗号),因为它与逗号完全等价。Hash变量由偶数个元素组成的列表来声明,其中偶数下标(0、2、……)的元素都被当做字符串使用。

    与array一样,你也需要用美元符号来存取hash中的值,因为取到的值是scalar而非hash:

    1. print $scientists{"Newton"}; # "Isaac"
    2. print $scientists{"Einstein"}; # "Albert"
    3. print $scientists{"Darwin"}; # "Charles"
    4. print $scientists{"Dyson"}; # 返回undef,打印""并且抛出一个警告

    注意在这里使用的花括号。同样的,同时存在scalar变量$var和包含scalar元素$var{"foo"}的hash变量%var是没有冲突的。

    1. my @scientists = %scientists;

    然而有一点与array不同,hash中的键没有特定的保存顺序,而是以一种比较高效的方式进行存储。因此,需要注意转换后的array会将hash中的键值对重新排列次序

    1. print "@scientists"; # 输出可能是"Einstein Albert Darwin Charles Newton Isaac"

    回顾一下,我们使用方括号来取array中的值,而使用花括号来取hash中的值。方括号是一个有效的数值运算符,而花括号是一个有效的字符串运算符,因此事实上,作为下标的值是数值还是字符串类型其实并不重要(译者注:正如前文所提到的,scalar以什么方式参与运算取决于运算符):

    列表(Lists)

    Perl中的列表与array和hash都不一样。你已经见过一些列表了:

    1. (
    2. "print",
    3. "these",
    4. "strings",
    5. "out",
    6. "for",
    7. "me",
    8. )
    9. (
    10. "Newton" => "Isaac",
    11. "Einstein" => "Albert",

    列表不是一个变量列表是一个暂存的,可以被赋值到一个array或者hash变量,这就是为什么声明array和hash的语法竟完全一样。在许多情况下“列表”和“array”这两个词可以混用,而在同样多的情况下,列表和array表现出微妙的区别,并且具有极其容易混淆的行为。

    好的,回想一下=>只是,的一种伪装,然后看一下下面的例子:

    1. ("one", 1, "three", 3, "five", 5)
    2. ("one" => 1, "three" => 3, "five" => 5)

    使用=>暗示了其中一个是hash的声明(译者注:第二个),而另一个是array的声明,但就这两个列表自身并没有声明任何东西,它们只是列表,而且是完全相同的列表。同样的:

    1. ()

    这里甚至没有任何变量类型的提示,这个列表可以用来声明一个空array或者空hash,而作为perl解释器则完全无法知道将会是哪一种。一旦你理解了这一点,你也就能理解Perl的这个事实:列表不能嵌套。我们可以试一下:

    1. my @array = (
    2. "apples",
    3. "bananas",
    4. (
    5. "inner",
    6. "list",
    7. "several",
    8. "entries",
    9. ),
    10. "cherries",
    11. );

    Perl无法知道("inner", "list", "several", "entries")应该是array还是hash,因此Perl假设两者都不是,而将其扁平化为一个一维长列表

    1. print $array[0]; # "apples"
    2. print $array[1]; # "bananas"
    3. print $array[2]; # "inner"
    4. print $array[3]; # "list"
    5. print $array[4]; # "several"
    6. print $array[5]; # "entries"
    7. print $array[6]; # "cherries"

    即使使用fat comma也会是同样的情况:

    1. my %hash = (
    2. "beer" => "good",
    3. "bananas" => (
    4. "green" => "wait",
    5. "yellow" => "eat",
    6. ),
    7. );
    8. # 上面的代码会抛出一个警告,因为我们尝试用7个元素的列表来初始化这个hash
    9. print $hash{"beer"}; # "good"
    10. print $hash{"bananas"}; # "green"
    11. print $hash{"wait"}; # "yellow";
    12. print $hash{"eat"}; # undef,因此打印""并且抛出一个警告
    1. my @bones = ("humerus", ("jaw", "skull"), "tibia");
    2. my @fingers = ("thumb", "index", "middle", "ring", "little");
    3. print @parts;

    稍后会有更多关于这个问题的说明。