Chinaunix首页 | 论坛 | 博客
  • 博客访问: 537200
  • 博文数量: 55
  • 博客积分: 1520
  • 博客等级: 上尉
  • 技术积分: 661
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-19 22:01
文章存档

2013年(1)

2012年(1)

2011年(7)

2010年(16)

2009年(30)

我的朋友

分类:

2009-05-25 15:00:10

(注:本文不是原创,只是学习过程中的学习笔记.)

一.简单变量(标量变量)
        基本上,简单变量就是一个数据单元,这个单元可以是数字或字符串.在PERL中,所有的简单变量都有缺省初始值:"",即空字符.但是建议给所有变量赋初值,否则当程序变得大而复杂后,很容易出现不可预料且很难调试的错误.

        1.整型
                整型是PERL最常用的简单变量.8进制以0打头,16进制以0x打头.
                例:
                        $var1 = 12345;
                        $var2 = 047; (等于十进制的39)
                        $var3 = 0x1f; (等于十进制的31)
                PERL实际上把整数存在计算机中的浮点寄存器中,所以实际上被当作浮点数看待,整数实为浮点数的特例.

        2.浮点数
                如11.4, -0.3, .3, 3., 54.1e+02, 5.41e03等,浮点寄存器通常不能精确地存贮浮点数,从而产生误差,在运算和比较中要特别注意.指数的范围通常为-309到+308.
                例:
                        $value = 9.01e+21;

        3.字符串
                C程序员要注意,在PERL中,字符串的末尾并不含有隐含的NULL字符,NULL字符可以出现在串的任何位置.
                双引号内的字符串中支持简单变量替换,例如:
                        $number = 11;
                        $text = "This text contains the number $number.";
                        则$text的内容为:"This text contains the number 11."

                双引号内的字符串中支持转义字符,要在字符串中包含双引号或反斜线,则在其前加一个反斜线,反斜线还可以取消变量替换,你如:
                        $res = "A quote \" and A backslash \\";
                        $result = 14;
                        print ("The value of \$result is $result.\n")的结果为:
                                The value of $result is 14.

                可用\nnn(8进制)或\xnn(16进制)来表示ASCII字符,例如:
                        $result = "\377"; # this is the character 255,or EOF
                        $result = "\xff"; # this is also 255

                单引号字符串与双引号字符串有两个区别,一是没有变量替换功能,二是反斜线不支持转义字符(\'除外).
                单引号另一个特性是可以跨多行,例如:
                        $text = 'This is two
                        lines of text
                        ';
                与下句等效:
                        $text = "This is two\nlines of text\n";

                在perl中除了双引号和单引号外,还支持其它的引用操作符,除了简单的引入字符串,还提供了许多功能.
                详细如下表:
                        结构        结果(相当于)        是否插值        代表
                        q/str/      'str'               no              文字串
                        qq/str/     "str"               yes             文字串
                        注:结构列中的/可以替换成你自定义的字符.
                例:
                        my $test_str = q{I'm a word!};
                        my $test_str = qq[I'm a word!];
                        my $test_str = q/I'm a word!/;
                        my $test_str = qq#I'm a word!#;
                        注:不可以在引用内添加注释,例子中的第四行不是注释.
                ' " ', " \" ", ' \' ', " ' "等写法很难看,最好都改写成以上的这种直观的方式.

                字符串和数值的互相转换,例如:
                        $string = "43";
                        $number = 28;
                        $result = $string + $number;
                        则$result = 71
                若字符串中含有非数字的字符,则从左起至第一个非数字的字符,例如:
                        $result = "hello" * 5;
                        则$result = 0
                        $result = "12a34" +1;
                        则$result = 13

                字符串常用的操作符是连接操作符"."和重复操作符"x".
                例:
                        print "aaa"."bbb"."\n";
                        print "aaa"x3;
                        结果为:
                                aaabbb
                                aaaaaaaaa

        4.undef变量
                变量在第一次赋值前,会有一个特殊的值undef,意为"什么都没有".
                undef值既非数字,又非字符串.它是另外一种标量变量.
                undef值在需要数字的地方,它为0;在需要字符的地方,它为空串.
                例如:
                        #n未定义
                        $a = $n + 3;    #此时a等于3.
                        $b = $n."hello";    #此时b等于hello.
                要分辨标量值是undef还是0或空串,可以使用defined函数,它将在变量为undef时返回false,其余的情况返回true.
                        #n未定义
                        print defined($n)."\n";
                        $n = "";
                        print defined($n)."\n";
                如果要想自己定义一个undef变量,直接对其赋值undef即可.如:
                        $var = undef;


二.列表
        列表是包含在括号里的一序列的值,可以为任何值,也可为空,例如:
                (1, 5.3 , "hello" , 2),().
        注:只含有一个数值的列表(如:(43.2) )与该数值本身(即:43.2 )是不同的,但它们可以互相转化或赋值.
        列表例:
                (17, $var, "a string")
                (17, 26 << 2)
                (17, $var1 + $var2)
                ($value, "The answer is $value")

        如果列表内容都是字符串的话,可以采用qw简写的方式.
        如:
                ("fred", "barney", "betty", "wilma", "dino")
        简写形式如下
                qw(fred barney betty wilma dino)
        qw是一种引用,所以不可以里面添加注释,同时(可以换成自定义的字符,如qw#fred barney betty wilma dino#

        列表范围:
                (1..10) = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
                (2, 5..7, 11) = (2, 5, 6, 7, 11)
                (3..3) = (3)
        用于实数
                (2.1..5.3) = (2.1, 3.1 ,4.1, 5.1)
                (4.5..1.6) = ()
        用于字符串
                ("aaa".."aad") = ("aaa","aab", "aac", "aad")
                @day_of_month = ("01".."31")
        可包含变量或表达式
                ($var1..$var2+5)

        小技巧:
                $fred = "Fred";
                print (("Hello, " . $fred . "!\n") x 2);
        其结果为:
                Hello, Fred!
                Hello, Fred!


三.数组
        数组是用来存储列表的变量,与简单变量不同,数组变量以字符"@"打头,例如:
                @array = (1, 2, 3);
        注:
                (1)数组变量创建时初始值为空列表:().
                (2)因为PERL用@和$来区分数组变量和简单变量,所以同一个名字可以同时用于数组变量和简单变量,例如:
                        $var = 1;
                        @var = (11, 27.1, "a string");
                但这样很容易混淆,故不推荐.

        1.数组的存取
        对数组中的值通过下标存取,第一个元素下标为0.试图访问不存在的数组元素,则结果为undef,但如果给超出数组大小的元素赋值,则数组自动增长,原来没有的元素值为undef.例如:
                @array = (1, 2, 3, 4);
                $scalar = $array[0];
                array[3] = 5;
                现在@array的值为(1, 2, 3, 5)
                $scalar = $array[4];
                现在$scalar = null;
                $array[6] = 17;
                现在@array的值为(1,2,3,5,"","",17)
        此外,$#代表数组的最后一个元素下标,可利用它来获取数组的最后一个元素.如:
                @array = ('a', 1, 2, 'z', 'b');
                print $array[$#array];
                输出结果为b.
        要获取数组的最后一个元素,也可以直接使用下标-1,如$array[-1],因为PERL中,负数下标值从最后一个开始.

        数组间拷贝
                @result = @original;

        用数组给列表赋值
                @list1 = (2, 3, 4);
                @list2 = (1, @list1, 5);
                则现在@list2 = (1, 2, 3, 4, 5)

        数组对简单变量的赋值
                @array = (5, 7, 11);
                ($var1, $var2) = @array;
                此时$var1 = 5, $var2 = 7, 11被忽略
                @array = (5, 7);
                ($var1, $var2, $var3) = @array;
                此时$var1 = 5, $var2 = 7, $var3 =""(null)

        从标准输入(STDIN)给变量赋值
                $var = ;
                @array = ;
                # ^D为结束输入的符号

        2.字符串中的方括号和变量替换
                "$var[0]" 为数组@var的第一个元素.
                "$var\[0]" 将字符"["转义,等价于"$var"."[0]",$var被变量替换,[0]保持不变.
                "${var}[0]" 亦等价于"$var"."[0]".
                "$\{var}"则取消了大括号的变量替换功能,包含文字:${var}.

        3.数组的输出:
                @array = (1, 2, 3);
                print (@array, "\n");
                结果为:
                123

                @array = (1, 2, 3);
                print ("@array\n");
                结果为:
                1 2 3

        4.列表/数组的长度
        当数组变量出现在预期简单变量出现的地方,则PERL解释器取其长度.
                @array = (1, 2, 3);
                $scalar = @array;
                此时$scalar = 3,即@array的长度
                ($scalar) = @array;
                此时$scalar = 1,即@array第一个元素的值
        注:以数组的长度为循环次数可如下编程:
                $count = 1;
                while ($count <= @array)
                {
                        print ("element $count: $array[$count-1]\n");
                        $count++;
                }

        5.子数组
                @array = (1, 2, 3, 4, 5);
                @subarray = @array[0,1];
                则@subarray = (1, 2)
                @subarray2 = @array[1..3];
                则@subarray2 = (2,3,4)
                @array[0,1] = ("string", 46);
                则现在@array = ("string",46,3,4,5)
                @array[0..3] = (11, 22, 33, 44);
                则现在@array = (11,22,33,44,5)
                @array[1,2,3] = @array[3,2,4];
                则现在@array = (11,44,33,5,5)
                @array[0..2] = @array[3,4];
                则现在@array = (5,5,"",5,5)
                可以用子数组形式来交换元素:
                @array[1,2] = @array[2,1];

        6.有关数组的库函数
        pop和push--读写数组
                pop操作将数组的最后一个元素取出并返回.
                        @array = (123, 456, 789);
                        print pop(@array);
                        此时@array = (123, 456);
                        如果数组为空,那么pop什么都不做,返回undef.
                push操作将一个元素添加到数组末尾.
                        @array = (123, 456);
                        push(@array, 789);
                        此时@array = (123, 456, 789);
        shift和unshift--读写数组
                这两个函数与pop和push相近,所不同的时,pop/push是在数组末尾操作,而shift/unshift是在数组头操作.
        sort--按字符顺序排序
                @array = ("this", "is", "a","test");
                @array2 = sort(@array);
                此时@array2 = ("a", "is", "test", "this")
                @array = (70, 100, 8);
                @array = sort(@array);
                此时@array = (100, 70, 8)
        reverse--反转数组
                @array2 = reverse(@array);
                @array2 = reverse sort (@array);
        chop--数组去尾
                chop的意义是去掉STDIN(键盘)输入字符串时最后一个字符--换行符.而如果它作用到数组上,则将数组中每一个元素都做如此处理.
                @list = ("rabbit", "12345", "quartz");
                chop (@list);
                此时@list = ("rabbi", "1234","quart")
                注:chop与chomp相近
                        chop()函数,只是去除最后一个字符.
                        chomp()函数,就要首先判断最后一个字符是不是为"\n",他才去除.
        join/split--连接/拆分
                join的第一个参数是连接所用的中间字符,其余则为待连接的字符数组.
                $string = join(" ", "this", "is", "a", "string");
                结果为"this is a string"
                @list = ("words","and");
                $string = join("::", @list, "colons");
                结果为"words::and::colons"
                @array = split(/::/,$string);
                结果为@array = ("words", "and", "colons")


四.哈希表(关联数组)
        Perl定义了另一种数组,可以用任意简单变量值来访问其元素,这种数组叫做关联数组,也叫哈希表.
        为了区分关联数组变量与普通的数组变量,Perl使用%作为其首字符,而数组变量以@打头.
        与其它变量名一样,%后的第一个字符必须为字母,后续字符可以为字母,数字或下划线.

        1.访问关联数组的元素
        关联数组的下标可以为任何简单变量(标量)值,访问单个元素时以$符号打头,下标用大括号围起来.
        例如:
                $fruit{"bananas"}
                $number{3.14159}
                $integer{-7}
        简单变量也可作为下标.
                $fruit{$my_fruit}

        2.增加元素
        创建一个关联数组元素最简单的方法是赋值.
        例如:
                $fruit{"bananas"} = 1;
        把1赋给关联数组%fruit下标为bananas的元素,如果该元素不存在,则被创建.如果数组%fruit从未使用过,也被创建.
        以下程序计算一个文件中,首字母大写的单词出现的次数:
                  1 #!/usr/bin/perl -w
                  2
                  3 $inputline = "";
                  4 while ($inputline = )
                  5 {
                  6     while ($inputline =~ /\b[A-Z]\S*\b/g)
                  7     {
                  8         $word = $&;
                  9         $counter{$word} += 1;
                 10     }
                 11 }
                 12 foreach $keyword (keys(%counter))
                 13 {
                 14     print $keyword.":".$counter{$keyword}."\n";
                 15 }

                [root@server perl]# cat testfile
                Here is a line of Input.
                I love You.
                This Input contains some Capitalized words.

                [root@server perl]# ./testperl < testfile
                I:1
                You:1
                Input:2
                Here:1
                This:1
                Capitalized:1
        本程序用关联数组%counter跟踪首字母大写的单词,下标就用单词本身,元素值为该单词出现的次数.第12行使用了内嵌函数keys(),这个函数返回关联数组的下标列表,foreach语句就用此列表循环.
        注:关联数组总是随机存贮的,因此当你用keys()访问其所有元素时,不保证元素以任何顺序出现,特别值得一提的是,它们不会以被创建的顺序出现.
        要想控制关联数组元素出现的次序,可以用sort()函数对keys()返回值进行排列.
        如:
                foreach $keyword (sort keys(%counter))
                {
                        print $keyword.":".$counter{$keyword}."\n";
                }

        3.创建关联数组
        可以用单个赋值语句创建关联数组.
        如:
                %fruit = ("apples",17,"bananas",9,"oranges","none");
        此语句创建的关联数组含有下面三个元素:
                * 下标为apples的元素,值为17
                * 下标为bananas的元素,值为9
                * 下标为oranges的元素,值为none
        注:
                用列表给关联数组赋值时,Perl5允许使用"=>"或","来分隔下标与值,用"=>"可读性更好些,上面语句等效于:
                %fruit = ("apples"=>17,"bananas"=>9,"oranges"=>"none");

        4.从数组变量复制到关联数组
        与列表一样,也可以通过数组变量创建关联数组(当然,其元素数目应该为偶数).
        如:
                @fruit = ("apples",17,"bananas",9,"oranges","none");
                %fruit = @fruit;
        反之,可以把关联数组赋给数组变量
        如:
                %fruit = ("grapes",11,"lemons",27);
                @fruit = %fruit;
        注意:此语句中元素次序未定义,那么数组变量@fruit可能为("grapes",11,"lemons",27)或("lemons",27,"grapes",11).
        关联数组变量之间可以直接赋值.
        如:
                %fruit2 = %fruit1;
        还可以把数组变量同时赋给一些简单变量和一个关联数组变量.
        如:
                ($var1, $var2, %myarray) = @list;
        此语句把@list的第一个元素赋给$var1,第二个赋给$var2,其余的赋给%myarray.
        最后,关联数组可以通过函数返回值来创建,当然函数的返回值必须为列表.
        把split()函数的返回值赋给一个关联数组变量的例子:
                1: #!/usr/local/bin/perl
                2:
                3: $inputline = ;
                4: $inputline =~ s/^\s+|\s+\n$//g;
                5: %fruit = split(/\s+/, $inputline);
                6: print ("Number of bananas: $fruit{\"bananas\"}\n");
        运行结果如下:
                oranges 5 apples 7 bananas 11 cherries 6
                Number of bananas: 11

        5.元素的增删
        增加元素已经讲过,可以通过给一个未出现过的元素赋值来向关联数组中增加新元素.
        如:
                $fruit{"lime"} = 1;
        创建下标为lime、值为1的新元素.
        删除元素的方法是用内嵌函数delete,如欲删除上述元素.
        则:
                delete ($fruit{"lime"});
        注意:
                1.一定要使用delete函数来删除关联数组的元素,这是唯一的方法.
                2.一定不要对关联数组使用内嵌函数push、pop、shift及splice,因为其元素位置是随机的.

        6.列出数组的索引和值
        上面已经提到,keys()函数返回关联数组下标的列表.
        如:
                %fruit = ("apples", 9, "bananas", 23, "cherries", 11);
                @fruitsubs = keys(%fruits);
        这里,@fruitsubs被赋给apples、bananas、cherries构成的列表.
        再次提请注意,此列表没有次序,若想按字母顺序排列,可使用sort()函数.
                @fruitindexes = sort keys(%fruits);
        这样结果为("apples","bananas","cherries").
        类似的,内嵌函数values()返回关联数组值的列表.
        如:
                @fruitvalues = values(%fruits);
        这里,@fruitvalues可能的结果为(9,23.11),次序可能不同.

        7.用exists检验索引是否存在
        要查看hash中是否存在某个key,可以使用exists函数,如果hash中存在此key,则返回true,这和是否有对应的value无关.
        如:
                my %fruit = ("apples"=>9, "bananas"=>23, "cherries"=>11);
                if ( exists($fruit{"orange"}) )
                {
                        print $fruit{"orange"}
                }
        该段代码将不会有任何输出,因为HASH中没有orange这个key.

        8.用关联数组循环
        前面已经出现过利用keys()函数的foreach循环语句,这种循环效率比较低,因为每返回一个下标,还得再去寻找其值.
        如:
                foreach $holder (keys(%records))
                {
                        $record = $records{$holder};
                }
        Perl提供一种更有效的循环方式,使用内嵌函数each().
        如:
                %records = ("Maris", 61, "Aaron", 755, "Young", 511);
                while (($holder, $record) = each(%records))
                {
                        # stuff goes here
                }
        each()函数每次返回一个双元素的列表,其第一个元素为下标,第二个元素为相应的值,最后返回一个空列表.
        注意:千万不要在each()循环中添加或删除元素,否则会产生不可预料的后果.

        9.反转哈希表
        我们可以将hash反转:
                %inverse_hash = reverse %any_hash;
        这会将%any_hash展开成key/value对的列表,其列表如(key,value,key,value,key,value,……).然后,将其反转,得到(value,key,value,key,value,key,……).value和key的位置交换了.
        当将其存放在%inverse_hash,我们就可以查询对于%any_hash来说是value的字符串,因为现在它对于%inverse_hash来讲是key了,查询到的value对于%any_hash来讲属于key.
        这给我们提供了一种方法:查询“value”(现在成了key),得到“key”(现在成了value).


五.引用
        引用类似于C中的指针,用来指向数据项,而反引用则访问它所指向的实际数据.
        PERL中有两种类型的引用:直接引用和符号引用.
        直接引用就是按"地址"来引用数据项,可通过在变量前加\来获取地址.
        例:
                my @var = qw(one two three);
                my $ref = \@var;
        符号引用则不保存数据项的地址和类型,而是直接保存数据项的名称.
        例:
                $var = "hello";
                $ref = "var";

        1.读取引用所指的数据
        要读取引用所指向的数据,需要使用前缀反引用符号.
        例:
                my @var = qw(one two three);
                my $ref = \@var;
                print @$ref[0];        #输出one
        也可以使用箭头运算符.
                my @var = qw(one two three);
                my $ref = \@var;
                print $ref->[0];        #输出one

        2.匿名引用
        PERL引用的强大之处在于可以直接存储对标量,数组,哈希和子程序的引用,而不是他们的名称.
        例:
                my $arrayref = [1, 2, 3];        #[]可够成匿名数组
                printf $arrayref->[0];        #输出1

                my $varref = \"Hello!";
                print $$varref;                #输出Hello!

                my $hashref = {               #{}可够成匿名哈希表
                                'a' => 'A',
                                'b' => 'B',
                              };                           
                print $hashref->{a};        #输出A

        3.把引用用在子程序中
        例:
                sub output
                {
                        my ($a) = @_;
                        print $a->[2];
                }
                my @var = qw(one two three);
                output( \@var );                #输出three

        4.用ref函数确定引用类型
        当新的子程序在处理引用时,如何知道当前正处理的是何种类型的引用?
        用ref函数可以得到.ref函数可能会返回的值如下:
                REF
                SCALAR
                ARRAY
                HASH
                CODE
                GLOB
        例:
                my $varref = \"OK";
                my $arrayref = [1, 2, 3];
                print ref $varref;        #输出SCALAR
                print ref $arrayref;        #输出ARRAY

阅读(5950) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~