Perl学习笔记(1)——基础语法
Overview
Perl简介
Perl(Practical Extraction and Report Language 实用摘录与报表语言),具有高级语言强大的能力和灵活性,可以提供脚本语言(如sed和awk)的所有功能,擅长文本的处理。
Perl的安装
Linux系统:(一般默认已经安装了,不需要再安装)
- tar zxvf perl-XX.tar.gz
- 找到perl存放目录,删除原始配置信息:rm -f config.sh Policy.sh
- 使用默认安装,sh Cogfigure -de
- make
- make test
- make install
Windows系统:使用ActivePerl
基本语法
标量
在Perl中也有类似单数和复数的区别,标量(Scalar)代表单件事物。标量可以是数字或者字符串。
数字
可以分为以下几种类型:
- 浮点数
eg:345.25;1.25e5 - 整数
eg:145;6_123_456(允许下划线分隔) - 非十进制整数
eg:0255(8进制255);0xf8(16进制);0b100_0010(2进制,允许下划线分隔)
对于数字常用操作符有:
+、-、*、/、%(取模)、**(乘幂)
字符串
字符串由字母、数字及标点符号组成。字符串由两种形式:单引号中的字符串和双引号中的字符串。
- 单引号中的字符串:
1、除单引号和反斜线字符外,单引号内的所有字符都代表它们本身;
2、‘\’’表示单引号;
3、‘\’表示反斜线;
4、‘\n’表示反斜线和n这两个字符; - 双引号中的字符串:
1、反斜线是转义字符:
2、\n在双引号字符串中表示换行,单引号字符中没有这个含义;
3、双引号字符串支持变量的内插,即将双引号字符串中的变量替换为该变量的当前值;
4、$、@、”、\ 这4个字符在双引号字符串中具有特殊含义,如果要在双引号字符串中表示这些字符需要在前面加反斜线进行转义。
字符串操作符
- 拼接操作符“.”:将两个字符串连接起来
eg:“who”.“are”.“you?\n” = “who are you?\n” - 重复操作符“x”:将左边的操作数与它本身重复连接,重复次数由右边的操作数指定
eg:"hello"x3 # 结果为hellohellohello
标量变量
define:标量变量以“$”开头,后面接Perl标识符(由字母、数字、下划线组成,必须字母或者下划线开始)
要慎重使用Perl默认的一些变量
$ARGV, $_ ,$1, $2, … $n, $$, $@, $? , $! …
perl的一些特殊内置变量:
变量 | 含义 |
---|---|
$n | 包含上次模式匹配的第n个字符串 |
$_ | 默认输入和模式匹配的内容(如果不指定接收输入的量或执行模式匹配的字符串) |
$$ | 运行当前Perl脚本程序的进程号 |
$@ | 命令eval的错误消息。如果为空则表示eval命令执行成功 |
$? | 存放进程结束状态 |
$! | die命令抛出的信息(系统错误字符串) |
@ARGV | 传给Perl脚本的命令行参数列表 |
@_ | 传给子程序的参数列表 |
@INC | 再导入模块时需要搜索的目录列表 |
- 标量的赋值:使用等号对标量进行赋值
eg:$value = 5; - 双目赋值操作符:几乎所有用来求值的双目操作符都可以接上等号为双目赋值操作符
标量变量内插
- 标量变量在双引号字符串中可以被内插
- 输出“$” 符号需要前面加“\”转义,或者使用单引号字符串
#eg:
print “The price is \$5.\n”
print 'The price is $5'
- 如果在变量内插后紧接着输出字母、数字或下划线,可以使用花括号{}做区分
#eg:
$str = “today is ${year}_${mon}_${day}\n”
操作符
- 算数操作符: +、-、*、/、**、%
- 整数比较操作符: >、>=、<、<=、==、!=、<=>
note:<=>(比较,如果相等返回0;如果第一个数大返回1;如果第二个数大返回-1) - 字符串比较操作符: gt、ge、lt、le、eq、ne、cmp
note:cmp(比较,返回1,0或-1) - 比较过程:依次比较两个字符串里的字符,判断它们是否彼此相等或哪一个排在前面(a - 97 ,A - 65,后一个字母比前一个字母 ASCII码大1)
- 逻辑操作符
操作 | 操作符 |
---|---|
逻辑与 | && /and |
逻辑或 | || / or |
逻辑非 | !/not |
逻辑异或 | xor |
-
位操作符: &、|、~、^、<<、>>
note:不要将&用于负整数,因为perl会把它们转化为无符号数 -
赋值操作符: =、+=、-=、/=、**=、&=、|=、~=、^=、<<=、>>=、.=
-
自增自减操作符:++、–
note:++可以用于字符串,但在结尾字符为‘z’、‘Z’、‘9’时进位;不要直接使用–,将字符串转为数字再进行自减; -
条件操作符:? :
undef值和defined函数
undef
- 变量在首次赋值之前,其值为undef
- undef当成数字使用时会被视为0
- undef当成字符串使用时会被视为空字符串
- undef既不是数字也不是字符串
- 有些操作符在参数越界或者不合理时,会返回undef
- 注意undef是变量值,不能用其清空数组
defined
defined函数用来判断变量的值是否为undef,是返回0,不是返回1.
列表和数组
如果将Perl中的标量看成是单数的概念,那么列表和数组就是复数的概念。
列表是变量的有序集合,而数组是存储列表的变量;列表指的是数据,而数组指的是变量;列表的值不一定要放在数组里,但数组变量都包含一个列表(可能是空列表)
数组或列表中的每个元素都是单独的标量变量,这里变量都有相应的整数作为索引,索引值从0开始,依次加1。
列表的定义及初始化
eg:(5,8,9) #包含5,8,9三个数的一个列表;(“my”,“name”,“is”,“xiaoming”)#字符串列表
- 范围操作符 " .. ": (1..100) #包含1~100的一个列表
- 用qw符号定义单词列表:会将列表中每个元素当成单引号内的字符串,eg:qw(my name is xiaoming)
- 定义单词列表时允许使用任何标点符号作为分界符:
eg :qw !my name is xiaoming !;qw # my name is xiaoming #;
数组元素及其索引值
- 通过数组名加索引值来访问数组元素
#eg:
$array[0]= "just";
$array[1]= "for";
$array[2]= "test";
-
$#: 名字为arrs的 数组的第一个索引值为0,最后一个索引值为 $#arrs
-
负的数组索引值:数组最后元素的索引值为-1,倒数第二个元素的索引值为-2,…
eg:数组arrs有3个元素,则有效的负数索引值为-1,-2,-3
列表赋值
- 列表值可以赋给变量
#eg:
($fred,$bar)=("stone","rubble","bin";)
列表赋值中额外的值会被自动忽略,如果有多余的变量会被赋予undef。
- 可以用列表对数组进行赋值
#eg:
(array[0],array[1]) = qw/array list/;
数组的定义由@开始,后面接上数组名
eg:
my @arrays = qw/array list/;
my @arrays = (); #空数组
数组和列表操作符
- pop操作符:用于取出数组中最后元素(索引值最大的元素)并返回该元素的值;作用于空数组时,什么也不做,返回undef。
- push操作符:添加一个元素或一串元素到数组的末尾
- shift和unshift操作符
pop和push针对数组的末尾,而shift和unshift时针对数组的开头进行操作。shift取出数字的第一个元素,并返回该元素的值,unshift则添加一个元素或列表到数组的开头。 - foreach:
。foreach循环能够逐项遍历列表中的值,依次迭代
。控制变量本身并不是列表元素的复制品,而是列表元素本身;foreach循环中修改了控制变量的值,也就修改了这个列表元素的值。
。循环结束后,控制变量仍是循环执行之前的值。(perl会自动存储foreach循环控制变量,并在循环放回后还原) - revere:读取列表的值,并按相反的次序返回该列表
eg:
@arrays = reverse @arrays;
- sort :
sort操作符会读取列表的值,并根据内部的字符编码顺序,对它们进行排序。对ASCII编码府字符串而言,排序规则就是ASCII码序。注意字母和数字的ASCII码序的关系为:数字,大写字母,小写字母。也可以自定规则使用sort来排序。
数组列表操作符使用具体例子:
#!/user/bin/perl -w
#----------------------------------------------------------------
#Description:
# the example unsed to descrip the use of operations for
# list and arrays in Perl
#
#----------------------------------------------------------------
#--------------------------------------
# example for pop operation
print "\nExample for pop operator:\n";
print "-"x40 . "\n";
my @arrs_1 = (1,3,4,9,10,4);
print "original arrays = @arrs_1 \n";
my $val = pop(@arrs_1);
print "after one pop operation:arrs_1 = @arrs_1 and obtained value = $val \n";
pop (@arrs_1);
print "after two pop operations and arrs_1 = @arrs_1 \n";
#--------------------------------------
# example for push operation
print "\nExample for push operator:\n";
print "-"x40 . "\n";
push (@arrs_1,100);
print "after one push 100 operation and arrs_1 = @arrs_1 \n";
my @tests = qw(100 104 109);
push (@arrs_1,@tests);
print "after two push operations, tests = @tests and arrs_1 = @arrs_1 \n";
#--------------------------------------
# example for shift operation
my @arrs = (1,2);
print "\nExample for shift and unshift :\n";
print "-"x40 . "\n";
print "original arrays = @arrs \n";
$val = shift(@arrs);
print "after one shift operation, arrs = @arrs and obtained value = $val \n";
$val = shift(@arrs);
print "after two shift operations, arrs = @arrs and obtained value = $val \n";
$val = shift(@arrs);
print "after three shift operations :";
if (defined $arrs[0]){
print"arrs = @arrs";
}
else {
print "arrs = undef";
}
if (defined $val){
print "and obtained value = $val \n";
}
else {
print "and obtained value = undef";
}
unshift (@arrs,7);
print "after one unshift operation and arrs = @arrs \n";
@tests = 10 .. 20;
unshift (@arrs,@tests);
print "after two unshift operation: tests = @tests and arrs = @arrs \n";
#--------------------------------------
# example for foreach operation
print "\nExample for push operator:\n";
print "-"x40 . "\n";
$val = 1000;
print "before foreach : val = $val \n";
print "test foreach operator : arrs = ";
my $num = 0;
foreach my $val (@arrs){
print " "if (num > 0);
print "$val";
$num ++;
}
print "\n";
print "after foreach : val = $val \n";
#--------------------------------------
# example for reverse operation
print "\nExample for push operator:\n";
print "-"x40 . "\n";
@arrs = reverse @arrs;
print "after revers and arrs = @arrs \n";
#--------------------------------------
# example for sort operation
print "\nExample for push operator:\n";
print "-"x40 . "\n";
@arrs = sort @arrs;
print "after the default sort operation and arrs = @arrs \n";
@arrs = sort {$a <=> $b} @arrs;
print "after the default sort operation use \"<=>\" and arrs = @arrs \n";
结果:
标量上下文和列表上下文(重要)
-
上下文
上下文是指表达式所处的位置,Perl解析表达式的时候,要么希望得到一个标量,要么希望得到一个列表。表达式所在的位置,Perl期望得郅什么,就是该表达式的上下文。
同一个表达式在不同的上下文会有不同的含义。 -
scalar函数
可以使用scalar函数强制指定标量上下文。 -
例子
#!/user/bin/perl -w
use strict;
# ---------------------------------------------------------------------
# Description:
# The example used to show the example Scalar and List Context
# ---------------------------------------------------------------------
my @arrays = qw(example for scalar and list context);
print "\narrays = @arrays \n\n"; #list context
my @sorted = sort @arrays; #list context
print "after sorted and arrays = @sorted\n\n";
print "after sorted and scalar arrays = " . scalar @sorted . "\n\n"; #scalar context
my $num = @arrays; #scalar context
print "num = $num\n\n";
my @reversed = reverse @arrays;
print "reversed arrays = @reversed \n\n";
my $reversed_str = reverse @arrays;
print "reversed string = $reversed_str \n\n"
结果:
子程序
-
子程序定义:
。使用sub关键字定义子程序,由子程序名和花括号中的缩进代码组成;
。子程序可以在程序任意位置定义;
。无需对子程序进行事先申明(子程序定义时全局的);
。当出现重名子程序时,后面的定义会覆盖前面一个; -
子程序调用:使用与号“&” 加上子程序名来调用已定义的子程序。
&display();
&display;
sub display {
print "This is a example for subroutings \n";
}
-
子程序参数:
。在子程序调用的后面加上括号圈引得列表表达式可以传递参数列表到子程序中;
。子程序内部通过数组变量@_来接收参数;(@_是子程序的私有变量,在当前的子程序调用中,@_总是包含了它的参数列表) -
子程序中的私有变量:
。默认情况下,Perl中的变量都是全局变量;
。可以使用操作符my来申明私有变量;
。my申明的私有变量的作用范围被圈定在语句块中;
sub get_max_val {
my ($val1,$val2) = @_ ;
}
- 子程序返回值
。所有子程序都有返回值,子程序执行过程中,最后
一次执行的结果会被自动当成子程序返回值;
。需小心检查最后执行的是哪一个表达式,确定是期
望的返回值;
。可以使用return操作符从子程序返回某个值;
#!/user/bin/perl -w
use strict;
# ----------------------------------------------
# THe example used to show the example of subrooutines
my $val1 = 10;
my $val2 = 19;
my $max = &get_max_val ($val1,$val2);
print "\nval1 = $val1,val2 = $val2 ,and max value = $max \n\n";
$max = &get_max_val (my $m, my $n);
sub get_max_val {
my ($val1,$val2) = @_;
if (!defined $val1 || !defined $val2){
print "the given data is uninitialized.Exiting ...\n";
exit;
}
return $val1 if ($val1 > $val2);
return $val2 if ($val2 > $val1);
}
结果:
哈希
哈希是一种数据结构,和数组相同,可以容纳很多值(无上限),并能随机存取。哈希和数组的区别在于:数组使用数字来进行索引,而哈希使用名字(保证唯一的字符串)。哈希的索引值称为键值(key),和索引相对应的是值
(value)。因此哈希中存储的是一序列的键/值对。
另一种理解hash的方法是,把它看作一堆数据,每一个数据都有一个相应的标签。可以通过标签访问此标签对应的元素。但其中是没有“第一个”元素的概念的。
-
为什么使用哈希?
可以把哈希看做一个简单的数据库,可以根据一组数据检索出对应的另一组数据。如果你的任务是关于“查询重复的”,“唯一的”,“交叉引用的”“查询表”,hash很可能在这类应用中能帮上忙。 -
一些哈希的应用场景.
。根据主机名找对应的IP地址
。根据IP地址找主机名
。按单词统计出现的次数
。按驾照号码找出对应的姓名 -
哈希的申明和赋值
。使用“%”符号对哈希进行申明 :my %tab
。使用列表对哈希进行赋值,必须有偶数个成员(哈
希必须是键/值对)
。可用箭头符号"=>"将哈希赋值中的键/值区分开来
。哈希松绑操作时,键/值对不一定按照赋值顺序松绑 :my @arrays = %tab #哈希->列表
;
。哈希复制
my %newhash = %hash;
my %inversehash = reverse %hash;
#哈希值唯一的情况下才有效
- 访问哈希元素
。访问哈希中的单个元素和访问数组元素类似,只是使用花括号而非中括号
来制定索引;可以将单个哈希元素内插到双引号字符串中,整个哈希的内插不支持。
my $value = $scores{$key};
my $vaIue2 = $scores{"xiaoming"};
print "Xiaoli's score is $scores{"xiaoli"}"\n";
- %ENV
Pel可以通过%ENV这个哈希获取系统环境的配置信息。只要在Perl程序外设定了任何的环境变量,就可以通过%ENV这个特殊的哈希获得。 - keys :返回哈希的键值列表
my @names = keys %scores;
- values:返回哈希的值列表
my @scores = values %scores;
- each:两个元素的列表形式返回键/值对。每次对同一个哈希调用此函数,就回返回下一组键/值对,知道所有元素都被访问过(此时each会返回空列表)。
while (my ($names,$score)= each %scores);
- exists :检查哈希中是否存在指定的键
my $person = "xiaoming";
if (exists $scores{$person}) {
print "we have obtained the score for $person \n";
}
- delate:删除哈希中指定的键及其对应的值
delete $scores {$person};
peint Data :: Dunmper -> Dump ([\%scores],['scores']);
- 哈希例子
#!/user/bin/perl -w
use strict;
use Data::Dumper;
#-------------------------------------------------------
# This is a simple complete example for hash application
my $tab = " ";
my %scores = (
"xiaoming" => 78,
"xiaoli" => 89,
"xiaotong" => 89,
"xiaosong" => 90,
"xiaowang" => 96,
"xiaoshi" => 84,
);
print "\n the original score hash table content :\n";
print "-"x40 . "\n";
print Data::Dumper ->Dump([\%scores],['scores']);
my $summary = "";
$summary .= "\nthe following is the score summary information:\n";
$summary .= "-"x50 . "\n";
my $sum = 0;
while (my ($name,$score) = each %scores) {
$summary .= "${tab}${tab} $name ${tab} -- $score \n";
$sum += $score;
}
$summary .= "\n\n";
my @names = keys %scores;
my @scores = values %scores;
print "\n The obtained name list = @names \n";
print "\n The obtained score list = @scores \n";
my $num = @names;
my $average = $sum / $num;
print "\n The average score is $average \n\n";
print $summary;
my $person = "xiaoming";
if (exists $scores{$person}) {
print "We have obtained the score for $person \n";
}
delete $scores {$person};
print "\n The following is the scores hash context after delete $person information from the hash:\n";
print "-"x50 . "\n";
print Data::Dumper ->Dump([\%scores],['scores']);
print "\n";
$person = "xiaoli";
delete $scores{$person};
print "\n The following is the scores hash context after delete $person information from the hash:\n";
print "-"x50 . "\n";
print Data::Dumper ->Dump([\%scores],['scores']);
print "\n";
结果: