条件语句
- 和大多数语言一样,熟悉格式就好了
$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重名
- 注: