Perl(二)

条件语句

  • 和大多数语言一样,熟悉格式就好了
    $a = 20;
    if( $a < 20 ){
        # 布尔表达式为true时执行
        print "a 小于 20\n";    
    }elsif( $a == 30 ){
        # 条件为true时执行
        print "a 的值为 30\n";
    }else{ 
        # 布尔表达式为false时执行
        print "a大于20\n";
    }
    
    $a=2;
    unless( $a < 20 ){	# 和if相反
        # 布尔表达式为 false 时执行
        printf "a 大于等于 20\n";
    }elsif($a==2){
    	# 条件匹配时执行
        print "a=2\n";
    }else{
        # 无匹配项时执行
        print "给定的条件为 true\n";
    }
    
  • Switch
    use Switch;	# yum install perl-CPAN
     
    $var = 10;
    @array = (10, 20, 30);
    %hash = ('key1' => 10, 'key2' => 20);
     
    switch($var){
       case 10           { print "数字 10\n" }
       case "a"          { print "字符串 a" }
       case [1..10,42]   { print "数字在列表中" }
       case (\@array)    { print "数字在数组中" }	# 什么都能case
       case (\%hash)     { print "在哈希中" }
       else              { print "没有匹配的条件" }
    }
    
  • 三元运算符,简化if语句
    $name = "Roy";
    $favorite = 10;
    
    $status = ($favorite > 60) ? "帅哥" : "不帅";
    print "$name - $status\n";	# Roy-不帅
    

循环

  • while循环
    $a = 10;
    
    # 执行 while 循环
    while($a < 20){
       print "a 的值为 : $a\n";
       $a = $a + 1;
    }
    # do...while
    $b = 10; 
    do{
       printf "b 的值为: $b\n";
       $b = $b + 1;
    }while( $b < 15 );
    
  • until
    $a = 5;
    
    until($a > 10){	# 条件不成立执行,直到...
       print "a 的值为 : $a\n";
       $a = $a + 1;
    } 
    
  • for
    for( $a = 0; $a < 10; $a = $a + 1 ){	#  也可以 $a++
    	# 和C语言类似
        print "a 的值为: $a\n";
    }
    
  • foreach
    @list = (2, 12, 36, 42, 51);
    # 和python的 for in 类似
    foreach $a (@list){
        print "a 的值为: $a\n";
    }
    
  • 循环可以嵌套

运算符

  • 算术运算符
    • 加减乘除取余求幂,和其他语言一样
  • 比较
    • == != > < >= <=
    • <=>左小于右返回-1,大于右返回1,相等返回0
    • 也可用lt gt le ge这些表示,l表示小于,g表示大于,e表示等于
  • 赋值运算符
    • = += *= /= -= %= **=
  • 位运算
    • & | ^ ~与/或/异或/取反
    • << >>左移/右移
  • 逻辑运算符
    • and or not
    • && ||,C风格
  • 引号运算
    • q{abcd}:为字符串添加单引号
    • qq{abcd}:添加双引号
    • qx{abcd}:添加反引号
  • 其他
    .:连接两个字符串
    ++/--:自增自减

函数

  • 和大部分语言类似
    sub Hello{
       print "Hello, World!\n";
    }
    
    Hello();	# 调用
    # vim shift+a 光标移到最后并insert
    # linux 
    
  • _代表传入的全部参数,不必定义形参
    sub Average{
        $n = scalar(@_);	# 参数个数
        # 也可以使用 $_[0访问具体参数
        $sum = 0;
        foreach $a (@_){
    		$sum += $a;
        }
        print "平均值:", $sum/$n, "\n";
    }
    
    Average(10,20,30);	# 20
    
  • 同时传入标量和数组,会合并
    sub List{
        my @list = @_;	# 这个my有什么用?
        print "my list: @list\n";
        print "$_[1]\n";	# 1	传入时就合并了
    }
    
    $a = 10;
    @b = (1,2,3,4,5);
    
    List($a, @b);
    
  • 传入哈希时,它将复制到 @_中,哈希表将被展开为键/值组合的列表
    sub Hash	{
        %h1 = @_;	# 键/值组合的列表 哈希的列表形式,本质还是会解释成哈希
        print %h1,"\n";
        print $h1{'name'},"\n";
        print "--------\n";
    }
    %hash = (-name=>'roy', -age=>18);
    
    Hash((-name=>'roy', -age=>18));
    Hash(('name'=>'roy', 'age'=>18));
    Hash(%hash);
    Hash('a', %hash);	# roy18-namea-age 乱了
    
  • 返回值:如果没有使用 return 语句,则子程序的最后一行语句将作为返回值
    sub Return{
        return $_[0] + $_[1],"\n";
    }
    print Return(1,2);
    
  • 你应该发现了函数名习惯使用大写字母开头
  • 当我们传入多个哈希或者数组会被合并,失去了参数的界限,这需要使用引用解决
  • 之前函数定义中使用了my,用于申明私有变量,可以理解成其他语言中的局部变量
    sub My_Func{
        my $var = 18;
        print $var,"\n"; 
    }
    
    My_Func();sub My_Func{
        my $var1 = 18;
        print $var1,"\n";	# 18
        $var2 = 19;
        print $var2,"\n"; # 19 全局都可以用
    }
    
    My_Func();
    print $var1,"\n";	# 啥也没有
    print $var2,"\n";	# 19
    # 这个和python就是相反的
    # python默认是局部的,使用全局需要global声明一下
    
  • local,为全局变量提供临时值
    $string = "Roy";
    
    sub Func{
        local $string;	# 用local申明一下,类似python中的global,但是不影响外部变量值
        $string = "Allen";
        print "$string\n"
    }
    Func();
    
    print "外部:$string\n";
    
    • 既然不用全局变量,内部用my新定义一个局部的不久好了吗?这样显得多余
    • 其实他的作用主要体现在:使用local的函数中调用的其他函数也会使用这个临时值
    $string = "Roy";
    
    sub Func{
        local $string;	# 用local申明一下,类似python中的global,但是不影响外部变量值
        $string = "Allen";
        print "$string\n";
        Func2();
    }
    
    sub Func2{
        print "func2: $string\n";
    }
    
    Func();
    
    • 当我们需要这个函数接口乃至其调用的函数所使用的全局变量都发生改变,就可以使用local赋一个临时值!
    • 还是一个作用域的小tip
  • 静态变量,使用state申明
    use feature 'state';
    
    sub State{
        state $count = 0;
        print "$count\n";
        $count++;
    }
    for (1..4){	# for 循环的简写形式
        State();
    }
    
    • 静态变量只能在函数中创建和使用
    • 静态变量的作用
      • 隔离:全局变量和静态变量都是静态存储,全局变量在各个源程序中都有效,但静态静态变量仅限于定义的那个源文件中
      • 持久性:我们希望函数中局部变量的值在函数调用结束之后不会消失,在下一次调用该函数时,局部变量的值仍然存在。可以使用static声明;静态局部变量只在其被声明的代码块中是可见的
  • 有些函数在调用时会根据上下文(等号左侧类型)返回对应值
    # 标量上下文
    my $datestring = localtime( time );
    print $datestring,"\n";
    
    # 列表上下文
    ($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time);
    printf ("%d-%d-%d %d:%d:%d",$year+1990,$mon+1,$mday,$hour,$min,$sec);	# 使用占位符需要用printf
    

引用

  • 引用就是指针
  • 引用时标量类型
  • 可以指向变量、数组、哈希表(也叫关联数组)甚至子程序,可以应用在程序的任何地方
    -变量引用
    • 在变量名前加\,可以得到变的引用
    $scalarref = \$foo;     # 标量变量引用
    $arrayref  = \@ARGV;    # 列表的引用 数组
    $hashref   = \%ENV;     # 哈希的引用
    $coderef   = \&handler; # 函数引用
    $globref   = \*foo;     # GLOB句柄引用
    
  • 匿名数组引用
    $aref= [ 1,"foo",undef,13 ];		# 就是使用标量接收数组
    
  • 匿名哈希引用
    $href= { APR =>4, AUG =>8 };
    
  • 匿名函数引用
    $coderef = sub { print "Runoob!\n" };
    

取消引用

  • 取消引用可以根据不同的类型使用 $ @ %来取消
    $var = 10;
    $r = \$var;	# 引用
    # 原来是标量,就使用 $ 取消
    print "$var 为 : ", $$r, "\n";	# 10 为 : 10
    # 如果不确定原来引用的是什么,可以使用ref()判断引用的类型
    print ref($r),"\n";	# SCALAR
    
    @var = (1,2,3);
    $r = \@var;
    print "@var 为: ",  @$r, "\n";	# 1 2 3 为: 123   @取消引用
    
    %var = ('k1'=>666, 'k2'=>888);
    $r = \%var;
    print "%var 为 : ", %$r, "\n";	# %var 为 : k2888k1666	
    # 哈希不能直接输出
    
  • 调用引用的函数
    sub PrintHash{
       my (%hash) = @_;
       
       foreach $item (%hash){
          print "元素 : $item\n";
       }
    }
    %hash = ('name' => 'runoob', 'age' => 3);
     
    # 创建函数的引用
    $cref = \&PrintHash;
    # 使用引用调用函数
    &$cref(%hash);	# 相当于取消函数的引用
    
  • 之前说函数中解决参数合并的问题,传入列表或哈希的引用即可

循环引用

  • 什么时候用?
    my $foo = 100;
    $foo = \$foo;
    # 会导致内存泄漏
    

格式化输出

  • Perl 是一个非常强大的文本数据处理语言
  • 看个例子
    #!/usr/bin/perl
     
    $text = "google runoob taobao";
    format STDOUT =
    first: ^<<<<<  # 左边对齐,字符长度为6
        $text
    second: ^<<<<< # 左边对齐,字符长度为6
        $text
    third: ^<<<< # 左边对齐,字符长度为5,taobao 最后一个 o 被截断
        $text  
    .
    write
    # 输出:
    first: google
    second: runoob
    third: taoba
    
  • 再来一个例子
    #!/usr/bin/perl
     
    format EMPLOYEE =
    ===================================
    @<<<<<<<<<<<<<<<<<<<<<< @<< 	# @或者^都可以开头,空格隔开,后面的变量对应
    $name, $age
    @#####.##	# 其前面6位,小数点后两位
    $salary
    ===================================
    .
     
    select(STDOUT);
    $~ = EMPLOYEE;
     
    @n = ("Ali", "Runoob", "Jaffer");
    @a  = (20, 30, 40);
    @s = (2000.00, 2500.00, 4000.000);
     
    $i = 0;
    foreach (@n){
        $name = $_;	# 循环变量
        $age = $a[$i];
        $salary = $s[$i++];	# 先使用再++,在表达式中才有意义(这里也算表达式)
        write;
    }
    # 输出
    ===================================
    Ali                     20
      2000.00
    ===================================
    ===================================
    Runoob                  30
      2500.00
    ===================================
    ===================================
    Jaffer                  40
      4000.00
    ===================================
    

特殊变量

  • 特殊变量是阻碍小白看懂代码的一大因素
  • 很多特殊的变量有一个很长的英文名,操作系统变量 $! 可以写为 $OS_ERROR
  • 这里说的很全面,不过我们只需记住一些常用的
    • $_表示循环变量,一般和 foreach 使用

补充

  • 新增一些遇到的知识点
  • ||= //=>运算符
    $args{SILENT} ||= 0;	# 如果变量值undef,空字符串""以及0时,都会赋值为0
    
    # => 类似python参数列表中的 : ,指定变量应该是什么值或什么类型
    # 只是为了程序的美观和易维护而被使用的
    use constant VELAPP_RELEASE       => '/etc/velocity-app-release';	# constant 定义常量
    
    # // 等价于 先使用defined()判断,如果为真则。。。类似三元表达式
    my $emails = $args{EMAILS} // '';
    # 等价于
    my $emails = defined($args{EMAILS}) || '';	# 只有 $args{EMAILS} 未定义才会赋值 ''
    
  • 严格编码模式
    # 当我们开启这种模式,编码必须遵循一些规范
    # 	使用分号; 结尾
    # 	使用my申明局部变量
    # 	使用our声明全局变量
    use strict;
    use warnings;
    # 正经代码都会开启严格模式!
    
  • qw()函数,defined()函数
    @list = ("perl","Regular","network","web");
    # 可以等价于:
    @list = qw(perl Regular network web);
    
    # 检验某个值是否已经定义
    my $files = $args{FILES} if( defined( $args{FILES} ) );	# 如果没定义那 $files 也是undef
    # 注:空字符串和0 算定义了
    
  • eq 代表 ==ne代表!=,做比较判断的
    #.=
    $info{$str} .= ";$emails";	# 相当于 +=, 字符串拼接
    
    # m/'/
    m 表示匹配
    # s/'/\\\\'/g;
    s 表示替换
    
  • sprintf格式化
    # 建议使用单引号包裹字符串,双引号包裹占位符
    # 变量中的双引号用\\"转义,单引号会自动转义
    $cmd = sprintf('/bin/python /opt/autosupport/tools/asc_send_email.py --subject """%s""" --msg """%s""" --mode "%s"',$subj, $msg, $flag);
    
  • our,修饰变量,作用域在整个包;相对于my,作用域只在代码块{ }
    package vxos_common;	# 声明这个包
    use strict;
    use warnings;
    
    # 严格模式下,声明新的变量必须使用our/my,使用时可以用local私有化,或者直接使用
    our $var = 1;
    {
    	# 直接使用var,说明var肯定是已经定义了的全局变量
        $var = 2;	# 不能再使用our定义,不然会报错,道理很简单!
        print $var, "\n";
    }
    print $var, "\n";
    # 2  2
    
    our $var = 1;
    {
    	local $var;
        $var = 2;
        print $var, "\n";
    }
    print $var, "\n";
    # 2  1
    
    # 一个文件不能同时用our 和 my声明同名变量
    my $var = 1;	# 没有块包裹,作用域就是整个文件中没被块包裹的部分
    {
        my $var = 2;	# 这里如果不用my,$var会变成全局变量不报错
        print $var, "\n";
    }
    print $var, "\n";
    # 2  1
    
    {
    	$test = 1;
    	print $test;	# 这样就会报错,不严格!
    }
    
    • 注:local私有化全局变量,不能定义变量
    • 上面两个例子可以反复尝试就会发现规律:
      • our一般定在文件前面,use下面;可以配合local在块中
      • my只用在函数块中,不能和our重名
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Roy_Allen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值