Perl基本速成_玖富娱乐主管发布


玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。

本文是针对没有Perl基础,但想用perl一行式敕令庖代grep/awk/sed的人,用于速学Perl基础学问。

Perl一行式系列文章:Perl一行式递次

perl的-e选项

perl敕令的-e选项后能够誊写表达式,比方:

perl -e 'print "hello worldn"'

Perl中的函数挪用常常能够省略括号,所以print "hello worldn"透露表现的是print("hello worldn"),但实在不是老是能够省略括号,一样平常来讲只需不是本身界说的函数,都能够省略括号,除非少数涌现歧义的状况。

在unix下发起运用单引号围困perl -e的表达式,在windows下发起运用双引号围困表达式。本文一切操纵都是在Linux下操纵的。

若是表达式中有多个语句,各语句之间运用分号";"离隔。比方:

perl -e 'print "hello";print "world"."n"'

注重,上面运用了点号"."来衔接两个字符串。

稍后会诠释另外一个表达式选项"-E",它和"-e"功用险些一样,独一分歧的是"-E"会自动启用一些高版本的功用。

print、printf、say和sprintf

Perl中的print函数不会自动换行,所以须要手动加上"n"来换行

perl -e 'print "hello world"'
perl -e 'print "hello worldn"'

Perl中的say()函数会自动换行,用法和print完全一致。但要运用say,须要运用use指定版本号高于5.010,。

$ perl -e 'use 5.010;say "hello world"'
hello world

运用"-E"选项替换"-e",能够省略版本的指定,因为"-E"自动启用高版本功用。

$ perl -E 'say "hello world"'
hello world

Perl也支撑printf函数,语法花样是printf "format_string",expr,...。想必看本文的人都晓得怎样运用printf,所以只给个简朴示例。

$ perl -e 'printf "hello %sn", "Perl"'
hello Perl

sprintf()函数透露表现依照printf的体式格局举行花样化,然后生存起来。生存起来的内容能够赋值给变量。

$ perl -e '$a = sprintf "hello %sn", "Perl";print "$a"'
hello Perl

上面将花样化后的字符串helloPerln生存到了变量$a中,然后print输出了变量"$a"。

变量

Perl中声明变量x须要运用$x。比方:

$x = "abc"
$y = 33
($x,$y)=("abc",33)
${var} = 333  # 加大括号是范例写法

下面是一行式敕令中的变量运用示例:

perl -e '$a="hello world";print "$an"'

Perl中变量赋值时,老是会先盘算右侧的效果,再赋值给左侧的变量。所以,变量交流非常轻易:

($var1,$var2)=($var2,$var1)

关于一行式Perl递次,变量能够不必事前声明直接运用。

perl -e 'print $a   1,"n"'

若是想要推断变量是不是已界说,能够运用defined($var)

perl -e 'if(defined($a)){print $a,"n"}'

不带任何润饰的变量是全局变量,若是想要界说为局部变量,能够在变量前加上my。my是一个函数。

my $a = "abc"

关于Perl一行式递次来讲,险些不须要斟酌my。但及少数状况下须要运用大括号或别的语句块的时刻,能够运用my来声明局部变量,出了语句块局限变量就失效。

$ perl -e '
        $a = 33;
        {
            my $a = "abc";
            print $a,"n";
        }
        print $a,"n";'

数值、字符串和反斜线序列

比方:

4   3              # 7
3.12   3.22        # 6.34
"4abc"   "3xyz"    # 7
"abc"   "3xyz"     # 3
"1.2abc"   "3.1x"  # 4.3
1..6            # 1 2 3 4 5 6
1.2..6.4        # 1 2 3 4 5 6

须要诠释下上面的几行语句。

  1. 数值和字符串之间的转换取决于做甚么运算。比方加法透露表现数学运算,会让字符串转换成数值
  2. 浮点数和整数之间的转换依然取决于所处的情况,在须要整数的时刻浮点数会直接截断成整数

字符串运用单引号或双引号围困,别的,Perl中也有反引号,这3种援用和shell中的单、双、反引号相似。:

  • 双引号透露表现弱援用,变量能够在双引号中举行内容替换
  • 单引号透露表现强援用,内部不会举行变量替换,反斜线序列也会失效
    • 在unix下的perl一行式递次中因为一样平常运用单引号围困-e表达式,所以一行式perl中单引号对照罕用
    • 若是非要运用单引号,能够斟酌运用q()来援用,见下文对q、qq和qx的诠释
  • 反引号透露表现实行操纵系统敕令并获得敕令的输出效果,须要记着的是它自带跟随换行符(除非所实行敕令就没有带跟随换行)。比方$a = `date %F %T`$files = `ls /root`
$ perl -e '$a = `date  "%F %T"`;print $a'
2019-01-03 19:55:32

Perl中有以下几个罕见的反斜线序列:

n
r
t
l    # 将下个字母转换为小写
L    # 将背面的多个字母都转换为小写,直到碰到E
u    # 将下个字母转换为大写
U    # 将背面的多个字母都转换为大写,直到碰到E
Q    # 和E之间的一切字符都强迫看成字面符号
E    # L、U和Q的完毕符号

字符串衔接须要运用".",比方"abc"."def"等价于"abcdef"。字符串反复次数能够运用小写字母x,比方"a" x 3获得"aaa""abc" x 2获得abcabc

Perl中数值和字符、字符串都支撑自增、自减操纵。相干示例拜见Perl中的自增、自减操纵。

q、qq和qx

在Perl中,引号不肯定非要写成符号,能够运用q()来透露表现单引号、qq()来透露表现双引号、qx()透露表现反引号。个中这里的括号能够替换成别的成对的符号,比方qq{}、qq//、qq%%都是能够的。

运用q范例的援用能够制止在shell中一行式Perl递次的引号转义题目。

比方,在一行式Perl中想要保存单引号:

$ perl -e "print q(abc'd)"

数组

Perl中的数组素质上是一个列表(关于Perl一行式敕令,能够将列表等价于数组),要声明数组,运用@符号。

@arr = ("Perl", "Python", "Shell")
@{arr} = (1,2,3)  # 加上大括号是范例的写法
@empty = ()       # 空数组

誊写列表时,字符串须要运用引号围困,逗号分开各个元素。还能够运用qw()来写列表,不须要再运用逗号分开元素,而是运用空格,且每一个元素都默许以单引号的体式格局围困。所以下面是等价的:

@arr = qw(Perl Python Shell abcndef)
@arr = ('Perl','Python','Shell,'abcndef')

关于一行式的perl敕令,变量和数组能够直接运用而无需事前声明

数组能够直接放在双引号中输出,默许输出的时刻是用空格分开各元素。

$ perl -e '@arr=qw(Perl Python Shell);print "@arrn"'
Perl Python Shell

要取数组中的某个元素,运用$符号。第一个元素$arr[0],第二个元素$arr[1]。比方:

$ perl -e '@arr=qw(Perl Python Shell);print "$arr[1]n"'
Python

数组$#arr$#{arr}透露表现数组的末了一个数组索引值,所以数组元素个数即是该值加1。

若是想要直接获得数组的个数,将数组赋值给一个变量或许运用scalar()函数便可。这涉及到Perl的上下文学问,不是本文内容,所以记着便可。

$ perl -e '
        @arr = qw(Shell Perl PHP);
        $num = @arr;print "$numn";
        print scalar @arr,"n";'

数组的索引能够是负数,-1透露表现末了一个元素,-2透露表现倒数第二个元素。所以$arr[-1]等价于$arr[$#arr],都是末了一个元素。

数组切片

数组支撑切片功用,切片操纵运用@符号,切片操纵会返回一个新的列表(数组)。切片时同一个元素能够涌现屡次,且递次随便,这比别的言语的切片要自在的多。比方:

@arr = qw(Perl Python Shell Ruby PHP)
@arr[0]   # 取第一个元素构成一个新列表
@arr[1,1,0,-2]  # 取两次序递次2个元素,一次序递次1个元素,一次倒数第2个元素构成新列表
@arr[1..3]  # 以序列的体式格局取第2到第4个元素构成新列表

下面是一个示例:

$ perl -e '
        @arr=qw(Perl Python Shell Ruby PHP);
        print "@arr[1,1,0,-2]n"'
Python Python Perl Ruby

若是想要取从第2个到倒数第2个元素,能够运用这类切片体式格局@arr[1..$#{arr}-1]。比方:

$ perl -e '@arr=qw(Perl Python Shell Ruby PHP);
        print "@arr[1..$#{arr}-1]n"'
Python Shell Ruby

操纵数组相干函数

数组能够运用pop/push函数来移除、追加最尾部的一个元素,运用shift/unshift函数移除、插进去首部第一个元素。若是想要操纵中央某个元素,能够运用splice()函数。这些函数的用法拜见:增、删数组元素。

别的,另有sort()、reverse()函数,在Perl中sort太甚壮大,不适合在这里睁开诠释,所以记着它能够用来排序列表(数组)做简朴运用便可。比方:

$ perl -e '
        @arr=qw(Perl Python Shell Ruby PHP);
        @arr1 = sort @arr;
        print "@arr1n"'
PHP Perl Python Ruby Shell

关于sort还需注重的是,它不是在原地排序的,而是天生一个排序后的新列表,原数组中元素的递次实在不会受排序的影响。所以须要将这个新列表赋值给另外一个数组变量能力获得排序后的效果,正如上面的示例一样。

但也有技能能够直接输出排序后的效果,并且这个技能非常有效:

$ perl -e '
         @arr=qw(Perl Python Shell Ruby PHP);
         print "@{ [ sort @arr ] }n"'
PHP Perl Python Ruby Shell

这属于Perl的高等技能,这里大抵诠释一下。它分红2个局部:

  • 第一局部是[],它透露表现组织一个匿名列表,匿名列表的内容能够来自于字面元素,也能够来自函数的效果或许表达式的效果,正如上面是将sort函数排序的效果组织成匿名列表;
  • 第二局部是@{xxx},它透露表现将列表xxx援用举行消除,然后能够插进去到双引号中举行输出。

所以,当想要将某个操纵的效果直接输出时,就能够接纳这类体式格局:

@{ [ something you do ] }

遍历数组

要遍历数组,能够运用for、foreach、each,固然也能够运用while,只不外运用for/foreach/each要更轻易。关于for/foreach/each/while细致的内容,见后文。

# foreach遍历数组
perl -e '
        @arr=qw(Perl Python Shell Ruby PHP);
        foreach $i (@arr){print "$in"}'

# for遍历数组:元素存在性测试遍历法
perl -e '
        @arr=qw(Perl Python Shell Ruby PHP);
        for $i (@arr){print "$in"}'

# for遍历数组:索引遍历法
perl -e '
        @arr=qw(Perl Python Shell Ruby PHP);
        for($i=0; $i<=$#arr; $i  ){print "$arr[$i]n"}'

# each遍历数组:key/value遍历
perl -e '
        @arr=qw(Perl Python Shell Ruby PHP);
        while (($index, $value) = each(@arr)){
            print "$index: $valuen"
        }'

必需注重的是,Perl中for/foreach以元素存在性测试遍用时,控制变量$i是各个元素的援用,而不是复制各个元素再赋值给$i,所以在遍历过程当中修正$i的值会直接修正原数组。

$ perl -e '
        @arr=qw(Perl Python Shell Ruby PHP);
        for $i (@arr){$i = $i."X"};  # 为每一个元素加跟随字符"X"
        print "@arrn"'
PerlX PythonX ShellX RubyX PHPX

split()和join()函数

join()用于将列表衔接成字符串,split()用于将字符串支解成列表。

join $sep,$list
split /pattern_sep/,$string,limit

细致用法和示例拜见:Perl处置惩罚数据(一):s替换、split和join。下面是两个简朴示例:

print join "--",a,b,c,d,e;   # 输出"a--b--c--d--e"

$str="abc:def::1234:xyz";
@list = split /:/,$str;

上面的字符串支解后将有5个元素:abc,def,空,1234,xyz。

hash(联系干系数组)

Perl也支撑hash数据构造,hash构造中key/value逐一映照,和Shell中的联系干系数组是一个观点。

在Perl中,不管是数组照样hash构造,素质都是列表。所以下面的列表数据能够认为是数组,也能够认为是hash,关键在于它赋值给甚么范例。

("name","longshuai","age",23)

在Perl中,数组范例运用@前缀透露表现,hash范例则运用%前缀透露表现。

所以,下面的透露表现hash构造:

%Person = ("name","longshuai","age",23)
%Person = qw(name longshuai age 23)

列表作为hash构造时,每两个元素构成一个key/value对,个中key局部必需是字符串范例。所以上面的hash构造透露表现的映照干系为:

%Person = (
        name => "longshuai",
        age  => 23,
)

实际上,上面运用胖箭头=>的写法在Perl中是许可且引荐的,它是元素分开符逗号的另外一种透露表现体式格局,且运用胖箭头更能展示逐一对应的干系。在运用胖箭头的写法时,若是key是相符定名范例的,能够省略key的引号(因为它是字符串,一般状况下是应当加引号围困的),正如上面所写的花样。

hash数据不克不及在双引号中举行内容替换,能够直接输出它,但直接输出时hash的元素是紧挨在一起的,这透露表现hash的字符串化。

$ perl -e '
        %hash = qw(name longshuai age 23);
        print "%hash","n"'
%hash

$ perl -e '
        %hash = qw(name longshuai age 23);
        print %hash,"n"'
age23namelongshuai

从hash中取元素运用$透露表现,如$hash{KEY},从hash中切片运用@透露表现,如@hash{KEY1,KEY2}这和数组是一样的。虽然hash范例本身不克不及在双引号中举行内容替换,但hash取值或许hash切片能够在双引号中替换

$ perl -e '
        %hash = (name=>"longshuai",age=>23);
        print "$hash{name}","n"'
longshuai

$ perl -e '
        %hash = (name=>"longshuai",age=>23);
        print "@hash{name,name,age,age}","n"'
longshuai longshuai 23 23

hash相干函数

主要有keys()、values()、exists()和delete()。

  • keys()返回hash构造中一切key构成的列表。比方keys %hash
  • values()则返回hash构造中一切value构成的列表。比方values %hash
  • exists()用来检测hash构造中元素是不是存在。比方exists $hash{KEY}
  • delete()用来删除hash中的一个元素。比方delete $hash{KEY}

下面是keys和values函数的示例。

$ perl -e '
        %hash = (name=>"longshuai",age=>23);
        print "keys:n";
        print keys %hash,"n";
        print "values:n";
        print values %hash,"n";'
keys:
agename
values:
23longshuai

看起来不是很爽,所以赋值给数组再来输出。

$ perl -e '
        %hash = (name=>"longshuai",age=>23);
        @keys = keys %hash;
        @values = values %hash;
        print "=========n";
        print "@keysn";
        print "=========n";
        print "@valuesn";'
=========
age name
=========
23 longshuai

怎样晓得hash构造中有多少个key/value对?是不是记得将数组(列表)赋值给一个变量时,获得的就是它的个数?

$ perl -e '
        %hash = (name=>"longshuai",age=>23);
        $nums = keys %hash;
        print "$numsn";'
2

若是想要直接输出个数而不是先赋值给变量,能够对一个列表运用函数scalar(),它会强迫让Perl将列表看成标量(变量)

$ perl -e '
        %hash = (name=>"longshuai",age=>23);
        print scalar keys %hash,"n";'
2

怎样排序hash构造?只需对keys的效果运用sort/reverse函数,再举行遍历输出便可。

$ perl -e '
        %hash = (name=>"longshuai",age=>23);
        for $key (sort keys %hash){
            print "$key => $hash{$key}n";
        }'
age => 23
name => longshuai

遍历hash

要遍历hash构造,能够运用while each或许for/foreach遍历hash的key或value。

# 运用while   each
$ perl -e '
        %hash = (name=>"longshuai",age=>23);
        while(($key,$value) = each %hash){
                print "$key => $value","n"
        }'
name => longshuai
age => 23

# 运用for或foreach去遍历keys或values
$ perl -e '
        %hash = (name=>"longshuai",age=>23);
        for $key (keys %hash){
                print "$key => $hash{$key}","n"
        }'
age => 23
name => longshuai

默许变量$_、@ARGV、@_

在Perl中,有一个非常迥殊的变量$_,它透露表现默许变量。

当没有为函数指定参数时、表达式中须要变量但却没给准时都邑运用这个默许变量$_

比方:

perl -e '$_="abcn";print'

print函数没有给参数,所以默许输出$_的内容。

再比方,for/foreach的遍历行动:

for $i (@arr){print "$in"}
for (@arr){print "$_n"}

for本该须要一个控制变量指向@arr中每一个元素,但若是没有给定,则运用默许变量$_作为控制变量。

用到默许变量的处所许多,没法列出一切运用$_的状况。所以简朴地总结是:只需某些操纵须要参数但却没有给定的时刻,就能够运用$_

$_是关于标量变量而言的默许变量。关于须要列表/数组的时刻,默许变量不再是$_,而是@ARGV@_:在自界说子递次(函数)内部,默许变量是@_,在自界说子递次外部,默许变量是@ARGV。比方:

$ perl -e '
        $name = shift;
        $age = shift;
        print "$name:$agen"' longshuai 23

默许数组(列表)变量对一行式perl敕令来讲能够遇不上,所以相识一下足以,只需能在须要的时刻看懂便可。

布尔值推断

在Perl中,真假的推断很简朴:

  1. 数值0为假,别的一切数值为真
  2. 字符串空""为假,字符串"0"为假,别的一切字符串为真(比方"00"为真)
  3. 空列表、空数组、undef、未界说的变量、数组等为假

注重,Perl中没有true和false的关键字,若是强迫写true/false,它们能够会被看成字符串,而字符串为真,所以它们都透露表现真。比方下面的两行,if的测试工具都认为是字符串而返回真。

perl -e "if(true){print "aaaan"}"
perl -e "if(false){print "aaaan"}"

巨细对照操纵

Perl的对照操纵符和bash完全相反。数值对照接纳符号,字符串对照接纳字母。

数值     字符串      意义
-----------------------------
==       eq        相称
!=       ne        不等
<        lt        小于
>        gt        大于
<=       le        小于或即是
>=       ge        大于或即是
<=>      cmp       返回值-1/0/1

末了一个<=>cmp用于对照两边的数值/字符串并返回状况码-1/0/1:

  • 小于则返回-1
  • 即是则返回0
  • 大于则返回1

关于<=>,若是对照的两边有一方不是数值,该操纵符将返回undef。

几个示例:

35 != 30   5       # false
35 == 35.0         # true
'35' eq '35.0'     # false(str compare)
'fred' lt 'bay'    # false
'fred' lt 'free'   # true
'red' eq 'red'     # true
'red' eq 'Red'     # false
' ' gt ''          # true
10<=>20            # -1
20<=>20            # 0
30<=>20            # 1

逻辑运算

Perl支撑逻辑与(and &&)、逻辑或(or ||)、逻辑非(not !)运算,还支撑一个分外的//操纵。它们都邑短路盘算。

符号范例的逻辑操纵&& || ! //优先级很高,为了保险,符号两边的表达式应当运用括号围困。关键字范例的逻辑操纵优先级很低,不须要运用括号围困。

($a > $b) && ($a < $c)
$a > $b and $a < $c

Perl的短路盘算非常迥殊,它返回的是末了运算的表达式的值。也就是说,它有返回值,经由过程返回值能够推断短路盘算的布尔逻辑是真照样假。

  • 若是这个返回值对应的布尔值为真,则全部短路盘算天然为真
  • 若是这个返回值对应的布尔值为假,则全部短路盘算天然为假

所以,这个返回值既包管短路盘算的效果不转变,又能获得返回值。这个返回值有时刻很有效,比方,能够经由过程逻辑或的操纵来设置默许值:

$name = $myname || "malongshuai"

上面的语句中,若是$myname为真,则$name被赋值为$myname,若是$myname为假,则赋值为"malongshuai"。

但上面有一种迥殊的状况,若是$myname已界说了,且其值为数值0或字符串"0",它也返回假。

这和预期有所争执,这时候能够运用//来替换||//透露表现只需左侧的内容已界说了就返回真,而不管左侧的内容代表的布尔值是真照样假。

$name = $myname // "malongshuai"

所以,就算$myname的值为0,$name也会赋值为0而不是"malongshuai"。

流程控制

if、unless和三目运算逻辑

语法花样:

# if语句
if(TEST){
    ...
} elsif {
    ...
} else{
    ...
}

# unless语句
unless(TEST){
    ...
}

# 三目运算符
expression ? if_true : if_false

if透露表现TEST为真的时刻,实行背面的语句块,不然实行elsif或else语句块。

unless则相反,TEST为假的时刻,实行背面的语句块。也就是等价于if(!TEST)。unless也有else/elsif块,但基础不会用,因为能够转换成if语句。

注重TEST局部,只需它的效果在布尔逻辑上是真,就透露表现真。比方:

if("abc"){}  # 真
if(0){}      # 假
if(0 > 1){}  # 假

where和until轮回

语法:

while(CONDITION){
    commands;
}

until(CONDITION){
    commands;
}

Perl的until和别的某些言语的until轮回有所分歧,Perl的until轮回,内部的commands主体能够一次也不会实行,因为Perl会先举行前提推断,以后提为假时就实行,若是第一次推断就为真,则直接退出until。

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。-

for和foreach轮回

Perl中的for轮回和Bash Shell相似,都支撑两种作风的for:

# (1).C言语作风的for
for(expr1;expr2;expr3){...}
for($i=0;$i<100;$i  ){...}

# (2).元素存在性测试的for
for $i (LIST){...}

# (3).元素存在性测试的for等价于foreach
foreach $i (LIST){...}

关于第一种for语法(即C言语作风的for),3个局部都能够省略,但分号不克不及省略:

  1. 省略第一局部expr1透露表现不做初始化
  2. 省略第二局部expr2透露表现不设置前提,意味着能够会无穷轮回
  3. 省略第三局部expr3透露表现不做任何操纵,能够也会无穷轮回

比方下面将3个局部全都省略,将会无穷轮回:

for(;;){
    print "never stop";
}

关于(2)和(3)的元素存在性测试的轮回,用来迭代遍历列表,每次迭代过程当中经由过程控制遍历$i援用以后被迭代的元素。注重:

  • $i是援用被迭代的元素,而不是复制列表中被迭代的元素然后赋值给$i,这意味着迭代过程当中修正$i会直接影响元素列表数据
  • $i能够省略,省略时运用默许变量$_
  • $i在遍历完毕后,会规复为遍历最先之前的值

比方:

$ perl -e '
        @arr = qw(Perl Shell Python Ruby PHP);
        for (@arr){
                $_ = $_."x";
        }
        print "@arrn"'
Perlx Shellx Pythonx Rubyx PHPx

上面没有显式指定控制变量,所以接纳默许变量$_。且在迭代过程当中为每一个$_都衔接了一个跟随字符"x",它会直接修正元素数组。

each遍历

each用来遍历hash或数组,每次迭代的过程当中,都猎取hash的key和value,数组的index(数值,从0最先)和元素值。

遍历hash:

#!/usr/bin/perl -w
use strict;

my %hash = (
    name1 => "longshuai",
    name2 => "wugui",
    name3 => "xiaofang",
    name4 => "woniu",
);

while(my($key,$value) = each %hash){
    print "$key => $valuen";
}

输出效果:

name4 => woniu
name3 => xiaofang
name2 => wugui
name1 => longshuai

遍历数组:

#!/usr/bin/perl -w
use strict;

my @arr = qw(Perl Shell Python PHP Ruby Rust);

while(my($key,$value) = each @arr){
    print "$key => $valuen";
}

输出效果:

0 => Perl
1 => Shell
2 => Python
3 => PHP
4 => Ruby
5 => Rust

表达式情势的流程控制语句

Perl支撑单表达式背面加流程控制符。以下:

command OPERATOR CONDITION;

比方:

print "true.n" if $m > $n;
print "true.n" unless $m > $n;
print "true.n" while $m > $n;
print "true.n" until $m > $n;
print "$_n" for @arr;
print "$_n" foreach @arr;

誊写时,许多时刻会分行并缩进控制符:

print "true.n"    # 注重没有分号末端
    if $m > $n;

改写的体式格局几个注重点:

  • 控制符左侧只能用一个敕令。除非运用do语句块,拜见下面诠释的do语句块
  • for/foreach的时刻,不克不及自界说控制变量,只能运用默许的$_
  • while或until轮回的时刻,因为要退出轮回,只能将退出轮回的前提放进前面的敕令中
    • 比方:print "abc",($n = 2) while $n < 10;
    • print "abc",($n = 2) until $n > 10;

改写的体式格局不克不及知足需求时,能够运用一般的流程构造。

大括号:运转一次的语句块

运用大括号围困一段语句,这些语句就属于这个语句块。这个语句块实际上是一个轮回块构造,只不外它只轮回一次。语句块有本身的局限,比方能够将变量界说为局部变量。

$ perl -e '
        $a = 33;
        {
            my $a = "abc";
            print $a,"n";
        }
        print $a,"n";'

do语句块

do语句块构造以下:

do {...}

do语句块像是匿名函数一样,没有名称,给定一个语句块,直接实行。do语句块的返回值是末了一个实行的语句的返回值。

比方,if-elsif-else分支构造赋值的语句:

if($gender eq "male"){
    $name="Malongshuai";
} elsif ($gender eq "female"){
    $name="Gaoxiaofang";
} else {
    $name="RenYao";
}

改写成do语句块:

$name=do{
    if($gender eq "male"){"Malongshuai"}
    elsif($gender eq "female") {"Gaoxiaofang"}
    else {"RenYao"}
};     # 注重末端的分号

前面说过,表达式情势的流程控制语句控制符左侧只能是一个敕令。比方:

print $_ 1,"n";print $_ 2,"n" if $_>3;

# 等价于下面两条语句:
print $_ 1,"n";
print $_ 2,"n" if $_>3;

运用do语句块,能够将多个语句组兼并看成一个语句。比方:

do{print $a 1,"n";print $a 2,"n"} if $a>3;

do{}中有本身的作用域局限,能够声明属于本身局限内的局部变量。

不要把do和大括号搞混了,大括号是被诠释的语句块局限的语法符号,能够用来符号本身的作用域局限。但do{}是语句,是被实行的语句块,也有本身的作用域局限。

last/next/redo/continue

  • last相当于别的言语里的break关键字,用于退出以后轮回块
  • (for/foreach/while/until/实行一次的语句块都属于轮回块),注重是只退出以后条理的轮回,不会退出外层轮回
  • next相当于别的言语里的continue关键字,用于跳入下一次迭代。一样只作用于以后条理的轮回
  • redo用于跳转到以后轮回条理的顶端,所以本次迭代中曾实行过的语句能够会再次实行
  • continue透露表现每轮轮回的主体实行完以后,都实行另外一段代码

熟习sed的人肯定很轻易明白这里redo和continue的作用。sed默许状况下会输出每一行被处置惩罚后的内容,这是因为它有一个和这里continue一样的逻辑,在perl敕令的"-p"选项也一样,到时刻会诠释这个continue的逻辑。sed的"-D"选项则是处置惩罚后立时回到sed表达式的顶端再次对形式空间举行处置惩罚,直到形式空间没有内容,这完成的是redo的逻辑。

BEGIN/END语句块

Perl像awk一样,也有BEGIN和END语句块,功用和awk是一样的。实际上Perl除BEGIN/END,另有CHECK、INIT和UNITCHECK语句块,不外关于一行式Perl递次,BEGIN/END就充足了。

Perl敕令行参数和ARGV

perl敕令行的参数存放在数组ARGV(@ARGV)中,所以能够接见$ARGV[n]、遍历,以至修正敕令行参数。

$ perl -e 'print "@ARGVn"' first second
first second

不难看出,@ARGV数组是从-e表达式以后才最先网络的。

实在ARGV数组有点迥殊,若是参数中有被读取的文件参数,那末每最先读一个文件,这个文件就从ARGV数组中剔除。所以,在递次编译时期(BEGIN语句块),ARGV数组中包含了完全的参数列表,处置惩罚第一个参数文件时,ARGV数组中包含了除此文件以外的别的参数列表,处置惩罚第二个参数文件时,ARGV数组中继承剔除这个文件参数。

比方,perl一行式敕令中,"-p"选项会输出参数文件的每一行被处置惩罚后的数据,也就是说它会读取参数文件。

$ echo aaaa > a.txt
$ echo bbbb > b.txt
$ perl -pe '
        BEGIN{
            print "in BEGIN:n";
            print "@ARGVn"
            }
        print "in argv file: @ARGVn";
        END{
            print "in END:n";
            print "@ARGVn"
        }
' a.txt b.txt

输出效果:

in BEGIN:
a.txt b.txt
in argv file: b.txt
aaaa
in argv file:
bbbb
in END:

实在,除ARGV数组@ARGV,另有一个ARGV变量$ARGV,它透露表现以后正在被读取的参数文件。

比方:

$ echo aaaa > a.txt
$ echo bbbb > b.txt
$ perl -pe '
        BEGIN{
            print "in BEGIN:n";
            print "@ARGVn"
            }
        print "reading me: $ARGVn";
' a.txt b.txt

输出效果:

in BEGIN:
a.txt b.txt
reading me: a.txt
aaaa
reading me: b.txt
bbbb

和shell交互:实行shell敕令

perl能够直接实行shell中的敕令体式格局有3种,但这里只引见两种:反引号(或qx)、system()函数。

反引号

反引号`COMMAND`qx(COMMAND)的体式格局是实行shell敕令COMMAND后,将COMMAND的输出效果生存下来作为返回值,它能够赋值给变量,也能够插进去到某个处所。就像shell中的反引号是一样的。

perl -e '$datetime = qx(date  "%F %T");print $datetime'

须要注重的是,反引号实行的效果中一样平常都邑保存跟随换行符(除非像printf一样明白不给跟随换行符),所以在print这些变量的时刻,能够不消指定"n"。或许为了连结赞同,运用chomp()或chop()函数操纵变量,去掉末了一个字符。

$ perl -e '
        $datetime = qx(date  "%F %T");
        chop $datetime;    # 或chomp $datetime
        print "$datetimen";'

还能够更轻便一些,直接在赋值语句上chop或chomp:

$ perl -e '
        chop($datetime = qx(date  "%F %T"));
        print "$datetimen";'

system()

第二种和shell交互的体式格局是system()函数。它会直接输出所实行的敕令,而不是将敕令的效果作为返回值。所以,system()函数不应当赋值给变量。

system()要实行的敕令局部须要运用引号围困。而关于一行式perl递次来讲,直接运用引号是一个困难,所以能够斟酌运用qq()、q()的体式格局。比方:

$ perl -e '
        system q(date  "%F %T");'
2019-01-03 20:18:34

若是肯定想要将system()的效果赋值给变量,获得的赋值效果是system()的返回值,而它的返回值透露表现的是敕令是不是胜利挪用(严格地说是wait()的返回值)。

$ perl -e '
        $datetime = system q(date  "%F %T");
        print "$datetimen";'
2019-01-03 20:23:21
0

还能够运用shell的管道、重定向等功用:

$myname="Malongshuai";
system "echo $myname >/tmp/a.txt";
system "cat <1.pl";
system 'find . -type f -name "*.pl" -print0 | xargs -0 -i ls -l {}';
system 'sleep 30 &';

system()的用法实在很庞杂,若是上面简朴运用单引号围困没法解决题目时,能够参考Perl和操纵系统交互(一):system、exec和反引号,这里面临system()的参数做了非常透辟的剖析。

和shell交互:向perl敕令行通报来自shell的数据

关于一行式敕令,能够会想要将shell的变量、shell中敕令的实行效果经由过程变量通报给perl敕令。自己网络了几种体式格局,或许不全,但应当充足敷衍一切状况。

体式格局一:经由过程情况变量$ENV{VAR}

perl递次在运转时,会自动注册一个hash构造%ENV,它网络来自shell的情况变量。比方读取shell的PATH情况变量、检察以后所运用的SHELL。

$ perl -e 'print "$ENV{PATH}n"'
$ perl -e 'print "$ENV{SHELL}n"'

所以,想要猎取shell的变量,能够先将其导出为情况变量,再从%ENV中猎取。

$ export name="longshuai"
$ perl -e 'print "$ENV{name}n"'

体式格局二:将perl -e 'xxxx'的单引号拆开重组,直接将须要被shell剖析的器械袒露给shell去诠释

$ name=longshuai
$ perl -e 'print "'$name'n"'
longshuai

上面分红三局部'print "'是一局部,$name是一局部,它没有被任何引号围困,所以直接袒露给shell举行变量替换,'n"'是末了一局部。

这类体式格局须要对shell的引号剖析非常闇练,对sed来讲这类写法有时刻是须要的,因为这是sed和shell交互的独一体式格局,但关于perl敕令行来讲,没有须要如许写,因为可读性太差,且很难写,常人真的不轻易写不来。

体式格局三:将变量放入参数地位,使其网络到ARGV数组中,然后在perl表达式中shift这些数据

$ name=longshuai
$ age=23
$ perl -e '
        $name = shift;
        $age = shift;
        print "$name,$agen"' $name $age
longshuai,23

注重上面的shift没有给定参数,所以shift会运用默许变量。因为shift期待的操纵工具是一个数组(列表),且不是在子递次内部(子递次内部透露表现在sub语句块内),所以运用默许数组@ARGV。也就说上面的代码等价于:

$ perl -e '
        $name = shift @ARGV;
        $age = shift @ARGV;
        print "$name,$agen"' $name $age

体式格局四:运用perl -s选项

perl的-s选项许可剖析--以后的-xxx=yyy花样的开关选项。

$ perl -e 'xxxxx' -- -name=abc -age=23 a.txt b.txt

--以后的参数,它们本该会被网络到ARGV中,但若是开启了-s选项,这些参数局部若是是-xxx=yyy花样的,则被剖析成perl的变量$xxx并赋值为yyy,而那些不是-xxx=yyy花样的参数则被网络到ARGV数组中。

比方:

$ perl -se '
        print "ARGV: @ARGVn";
        print "NAME & AGE: $name,$agen";
        ' -- -name="longshuai" -age=23 abc def
ARGV: abc def
NAME & AGE: longshuai,23

上面通报的参数是-name="longshuai" -age=23 abc def,因为开启了-s选项,所以剖析了两个perl变量$name=longshuai $age=23,别的两个bac def则被网络到ARGV数组中。

体式格局五:根绝运用shell,完全替换为perl。在perl中反引号或qx()也支撑运转shell递次

比方:

$ name=longshuai
$ perl -e '
        $name = qx(echo $name);
        print "name in perl: $name"'
name in perl: longshuai

$ perl -e '
        $time = qx(date  "%T");
        print "time in perl: $time"'
time in perl: 19:52:39

注重上面qx(echo $name)的反斜线弗成少,不然$name会被perl剖析,转义后能力够保存$符号被shell剖析。

Perl读写文件

一行式perl递次的重头戏天然是处置惩罚文本数据,所以有须要诠释下Perl是怎样读、写数据的。

读取范例输入<STDIN>

<STDIN>符号透露表现从范例输入中读取内容,若是没有,则守候输入。<STDIN>读取到的效果中,一样平常来讲都邑自带换行符(除非发生意外,或EOF非常)。

$ perl -e '$name=<STDIN>;print "your name is: $name";'
longshuai     # 这是我输入的内容
your name is: longshuai   # 这是输出的内容

因为读取的是范例输入,所以泉源能够是shell的管道、输入重定向等等。比方:

$ echo "longshuai" | perl -e '$name=<STDIN>;print "yourname is: $name";'
your name is: longshuai

在好比,推断行是不是为空行。

$ perl -e '
        $line=<STDIN>;
        if($line eq "n"){
            print "blank linen";
        } else {
            print "not blank: $line"
        }'

注重,<STDIN>每次只读取一行,碰到换行符就完毕此次读取。运用while轮回能够继承向后读取,或许将其放在一个须要列表的处所,也会一次性读取一切内容生存到列表中。

# 每次只读一行
$ echo -e "abcndef" | perl -e '$line=<STDIN>;print $line;'
abc

# 每次迭代一行
$ echo -e "abcndef" | perl -e 'while(<STDIN>){print}'
abc
def

# 一次性读取一切行生存在一个列表中
$ echo -e "abcndef" | perl -e 'print <STDIN>'
abc
def

别的须要注重的是,若是将<STDIN>显现生存在一个数组中,因为输出双引号围困的数组各元素是自带空格分开的,所以换行符会和空格兼并致使不整齐。

$ echo -e "abcndef" | perl -e '@arr=<STDIN>;print "@arr"'
abc
 def

解决办法是实行一下chomp()或chop()操纵,然后在输出时手动指定换行符。

$ echo -e "abcndef" | perl -e '@arr=<STDIN>;chomp @a;print "@arrn"'
abc def

读取文件输入<>

运用两个尖括号符号<>透露表现读取来自文件的输入,比方从敕令行参数@ARGV中通报文件作为输入源。这个符号被称为"钻石操纵符"。

比方读取并输出/etc/passwd和/etc/shadow文件,只需将它们放在表达式的背面便可:

$ perl -e '
        while(<>){
            print $_;  # 运用默许变量
        }' /etc/passwd

能够直接在perl递次中指定ARGV数组让<>读取,是不是还记得$ARGV变量透露表现的是以后正在读取的文件?

perl -e '@ARGV=qw(/etc/passwd);while(<>){print}'

一样平常来讲,只须要while(<>)中一次次的读完一切行就能够。但有时刻会想要在轮回内部继承读取下一行,就像sed的n和N敕令、awk的next敕令一样。这时候能够单独在轮回内部运用<>,透露表现继承读取一行。

比方,下面的代码透露表现读取每一行,但若是行首以字符串abc开首,则立时读取下一行。

perl -e '
        while(<>){
            if($_ =~ /^abc/){
                <>;
            }
            ...
        }'

文件句柄

实在<><STDIN>是两个迥殊的文件读取体式格局。若是想要以最一般的体式格局读取文件,须要翻开文件句柄,然后运用<FH>读取对应文件的数据。

翻开文件以供读取的体式格局为:

open FH, "<", "/tmp/a.log"
open $fh, "/tmp/a.log"     # 与上面等价

文件句柄名一样平常运用大写字母(如FH)或许直接运用变量(如$fh)。

然后读取便可:

while(<FH>){...}
while(<$fh>){...}

比方:

$ perl -e 'open FH,"/etc/passwd";while(<FH>){print}'

除翻开文件句柄以供读取,还能够翻开文件句柄以供写入:

open FH1,">","/tmp/a.log";   # 以掩盖写入的体式格局翻开文件/tmp/a.log
open FH2,">>","/tmp/a.log";  # 以追加写入的体式格局翻开文件/tmp/a.log

要写入数据到文件,直接运用print、say、printf便可,只不外须要在这些函数的第一个参数位上指定输出的目的。默许目的为STDOUT,也就是范例输出。

比方:

print FH1,"hello worldn";
say   FH,"hello worldn";
printf FH1,"hello worldn";

在向文件句柄写入数据时,若是运用的是变量情势的文件句柄,那末print/say/printf能够会没法辨别这个变量是文件句柄照样要输出的内容。所以,应当运用{$fh}的情势制止歧义。

print {$fh},"hello worldn";

正则表达式婚配和替换

本文通篇都不会深切诠释Perl正则,因为内容太多了,并且我已写好了一篇从0基础到深切控制Perl正则的文章Perl正则表达式超细致教程和s///替换的文章Perl的s替换敕令。

关于进修perl一行式递次来讲,无需特地去进修Perl正则,会基础正则和扩大正则足以。虽不消特地学Perl正则,但有须要晓得Perl的正则是怎样誊写的。

运用str =~ m/reg/符号透露表现要用右侧的正则表达式对左侧的数据举行婚配。正则表达式的誊写体式格局为m//s///,前者透露表现婚配,后者透露表现替换。关于m//s///,个中斜线能够替换为别的符号,划定规矩以下:

  • 双斜线能够替换为恣意别的对应符号,比方对称的括号类,m()m{}s()()s{}{}s<><>s[][],雷同的标点类,m!!m%%s!!!s###s%%%等等
  • 只有当m形式接纳双斜线的时刻,能够省略m字母,即//等价于m//
  • 若是正则表达式中涌现了和分开符雷同的字符,能够转义表达式中的符号,但更发起换分开符,比方/http:///转换成m%http://%

所以要婚配/替换内容,有以下两种体式格局:

  • 体式格局一:运用data =~ m/reg/data =~ s/reg/rep/,能够明白指定要对data对应的内容举行正则婚配或替换
  • 体式格局二:直接/reg/s/reg/rep/,因为省略了参数,所以运用默许参数变量,它等价于$_ =~ m/reg/$_ =~ s/reg/rep/,也就是对$_生存的内容举行正则婚配/替换

婚配

Perl中婚配操纵返回的是婚配胜利与否,胜利则返回真,婚配不胜利则返回假。固然,Perl供应了迥殊变量许可接见婚配到的内容,以至婚配内容之前的数据、婚配内容以后的数据都供应了相干变量以便接见。见下面的示例。

比方:

1.婚配给定字符串内容

$ perl -e '
        $name = "hello gaoxiaofang";
        if ($name =~ m/gao/){
            print "matchedn";
        }'

或许,直接将字符串拿来婚配:

"hello gaoxiaofang" =~ m/gao/;

2.婚配来自管道的每一行内容,婚配胜利的行则输出

while (<STDIN>){
    chomp;
    print "$_ was matched 'gao'n" if /gao/;
}

上面运用了默许的参数变量$_,它透露表现while迭代的每一行数据;上面还简写正则婚配体式格局/gao/,它等价于$_ =~ m/gao/

以下是实行效果:

$ echo -e "malongshuaingaoxiaofang" | perl -e "
        while (<STDIN>){
        chomp;
        print qq($_ was matched 'gao'n) if /gao/;
        }"
gaoxiaofang was matched 'gao'

3.婚配文件中每行数据

while (<>){
    chomp;
    if(/gao/){
        print "$_ was matched 'gao'n";
    }
}

替换

s///替换操纵是原地见效的,会直接影响原始数据。

$str = "ma xiaofang or ma longshuai";
$str =~ s/ma/gao/g;
print "$strn";

s///的返回值是替换胜利的次数,没有替换胜利返回值为0。所以,s///本身能够看成布尔值举行推断,如

if(s/reg/rep/){
    print "$_n";
}

print "$_n" if s/reg/rep/

while(s/reg/rep/){
        ...
}

若是想要直接输出替换后获得的字符串,能够加上r润饰符,这时候它不再返回替换胜利的次数,而是直接返回替换后的数据:

$ perl -e '
        $str = "ma xiaofang or ma longshuai";
        print $str =~ s/ma/gao/gr,"n";'
gao xiaofang or gao longshuai
-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。