PERL LEARN NOTE
目录基本表述
- perl的书写形式和shell的形式类似
- 需要在首行写shebang #!
- 注释符为#,仅能单行注释
- 多行注释应该有其他技巧
- perl中变量的类型有标量/数组/哈希
- 可以用my定义变量,变量得生命周期一直到代码块尾或程序为
ITEM | perl | bash |
---|---|---|
变量定义方法 | my | set |
写在程序开头
perl是很随意的语言,为了避免不必要的麻烦,可以在程序开头加如下command
- use warnings;
- use strict;
标量
标量的几种形式
- undef(类似于null/none)
- 数值
- 字符串
- 其他变量的引用
变量未初始化时默认赋值为undef
my $undef = undef;
print $undef; # 打印空字符串"",并且抛出一个警告
# 隐式的undef(译者注:未初始化的变量初值默认为undef):
my $undef2;
print $undef2; # 打印"",并且抛出完全一样的警告
my $num = 4040.5;
print $num; # "4040.5"
数值
数值表示
- perl dont care数值类型,统一按照双精度浮点数处理
- 除常规整数(正负零),较长的数字可以用下划线分割方便阅读(类似于verilog中的方法),5825_9567_1451_587
- 除常规浮点数外,也可以用科学计数法表示浮点数(整数也可以的),e or E ,2.4e3=2400, -1.2E3=-1200
- 二进制:以0b开头(零b)
- 八进制:以0开头(零)
- 十六进制:以0x开头(零x)
- 非十进制也可以使用下划线区分,0xacf6_c650_2386
数值运算
- 常规加减乘除运算
- 模运算%(求余)
- 指数运算**
- 二元赋值操作符:$num+=5等,类似于c语言
字符串
- 最短的字符串不包含任何字符,最长的字符串可以填满内存
- 单引号字符串:不具备转义功能('\'\\'结果有点诡异)
- 双引号字符串:具备转义功能
- 字符串拼接:使用.实现字符串拼接
- 字符串重复:"string" x number,实现string几次重复
分隔符
- perl提供和bash一样的分隔符{},区分普通字符串和变量名
$what =“brontosaurus steak”;
$n = 3;
print “fred ate $n $whats.\n”; #不是steaks,而是$whats 的值
print “fred ate $n ${what}s.\n”; #现在是使用变量$what
print “fred ate $n $what”. “s.\n”; #另一种方法
print ‘fred ate ’. $n . ‘’. $what . “s.\n”; #一种复杂的方法
布尔类型
perl没有内置布尔类型,通常被判定为false的返回值有:
- 数值0
- 空字符串""
- 字符串"0"
- undef
判定为true时通常返回值为1
比较运算符
ITEM | 数字 | 字符串 |
---|---|---|
等于 | == | eq |
不等 | != | ne |
小于 | < | lt |
大于 | > | gt |
小于或等于 | <= | le |
大于或等于 | >= | ge |
# 经典错误
print "yes" == "no"; # "1" 并且抛出两个警告,按数值方式参与运算,两边求值结果都是0
35 != 30+5 #false
35 == 35.0 #true
‘35’eq‘35.0’ #false (按照字符串比较)
‘fred’lt ‘barney’ #false
‘fred’lt ‘free’ #true
‘fred’eq ‘fred’ #true
‘fred’eq ‘Fred’ #false
‘’gt ‘’ #true
STDIO
- 输出:print
- 输入:<STDIN>
$line = <STDIN>;
if($line eq “\n”){
print “That was just a blank line!\n”;
}
else{
print “That line of input was: $line”;
}
chmop
- 去掉字符串末尾的换行符
- 用法:chmop($text);
- 小技巧:chmop($text = <STDIN>) #读入但不含换行符
- 结尾有两个或以上换行符,chmop仅去掉一个
undef
- 为赋值变量通常默认赋值为undef
- undef既不是数字也不是字符,是另一种标量类型
- 在合适的“语境”下会自动转换为0或空字符串
- define检测变量是否为undef,undef时返回false,其余返回true
$madonna = <STDIN>;
If ($defined ($madonna)){
print “The input was $madonna”;
}else{
print “No input available!\n”;
}
条件语句
if
条件为真时执行code block
if(condition1){
}elseif(condition2){
}else{
}
unless
条件为假时执行unless code block
unless(condition){
}else{
}
循环语句
while
- 和C类似,条件为真执行while语句
$count = 0;
while ($count < 10) {
$count + = 2;
print “count is now $count\n”; #打印出2 4 6 8 10
}
foreach
- 从列表第一个元素遍历至最后一个
foreach $rock (qw/ bedrock slate lava /){
print “One rock is $rock.\n”; #打印出3 种rocks
}
@rocks = qw/ bedrock slate lava /;
foreach $rocks(@rocks){
$rock = “\t$rock”; #@rocks 的每一个元素前加入一个tab
$rock . = “\n”; #每一个元素后加一个换行符
}
print “The rocks are:\n”,@rocks; #每一个元素都被缩进了,并且一个元素占一行
for
和c语言for循环类似
for(my $i=0;$i<=number;$i++){
}
do while
do while会执行至少一次(条件为假时)
my $a = 10;
do {
print "the value is $a now\n";
$a--;
}
while($a >= 1);
print "the value is less than 1";
until
do until
数组
- 数组是列表的有序集合,列表是标量的有序集合
- 数组中的元素从0开始索引,依次递增1
数组声明
整体赋值
my @array = (
"print",
"these",
"strings",
"out",
"for",
"me", # 末尾多余的逗号语法上是允许的
)
单独赋值
$array[0] = "print";
数组存取
用$符号存取数组中的值,因为数组中的每个元素是标量
[下标为正]
print $array[0]; # "print"
print $array[1]; # "these"
print $array[2]; # "strings"
print $array[3]; # "out"
print $array[4]; # "for"
print $array[5]; # "me"
print $array[6]; # 返回undef,打印""并且抛出一个警告
[下标为负]
print $array[-1]; # "me"
print $array[-2]; # "for"
print $array[-3]; # "out"
print $array[-4]; # "strings"
print $array[-5]; # "these"
print $array[-6]; # "print"
print $array[-7]; # 返回undef,打印""并且抛出一个警告
范围操作
- (1 .. 5)等价于(1,2,3,4,5)
- (1.7 .. 5.7)等价于(1,2,3,4,5)
- (1,6 .. 8,10)等价于(1,6,7,8,10)
- ($m,$n)
- 左侧数值要大于右侧
- 字符串列表缩写:qw(bird dog stone)等价于("bird","dog","stone");qw中不能引用需要转义的数值或符号
($fred, $barney, $dino) = (“flintstone”, “rubble”, undef);
($fred, $barney) = ($barney, $fred) #交换两个变量
($betty[0],$betty[1]) = ($betty[1],$betty[0]);
($fred, $barney) = qw <flintstone rubble slate granite>; #两个值被忽略了
($wilma,$dino) = qw[flintstone]; #$dino 为undef
@rocks = qw / bedrock slate lava /;
@tiny = (); #空表
@giant = 1..1e5; #包含100,000 个元素的表
@stuff = (@giant, undef, @giant); #包含200,001 个元素的表
@dino = “granite”;
@quarry = (@rocks, “crushed rock”, @tiny, $dino);
@copy = @quarry; #将一个数组中的值拷贝的另一个数组中
tips:
- 变量$number和数组$number[?]是不冲突的
- 数组索引值超出下标范围返回值为undef
- 最后一个数组的索引表示为$#array
- 数组的长度表示:scalar @array
- 字符串中包含@会使得程序索引@sring这个数据,所以可以采用单引号或是@的形式
数组操作
- pop:取出数组中最后一个元素并返回值;如果数组为空,那pop 什么也不做(因为没有元素可以移出),并返回undef
- push:在数组末尾插入一个元素
- shift:取出数组中第一个元素并返回值
- unshift:在数组头插入一个元素
- reverse:反向排列
- sort:按字母顺序排列
- split:
my $string="This is a kind of dynamic array";
my @array;
@array=split('a',$string);
foreach(@array)
{
print "$_ \n”;
# This is a special variable which stores the current value.
}
#result:
Output:
This is
kind of dyn
mic
rr
y
子程序
- 子程序的位置是任意的
- 子程序的定义是全局的
- 如果有两个命名相同的子程序,后一个会覆盖前一个
一般形式:
sub marine {
$n + = 1; #全局变量$n
print “Hello, sailor number $n!\n”;
}
调用子程序方法:&sub_function_name,返回值为最后一个被计算的表达式。
子程序参数
子程序可以通过调用参数的方式,简化不必要的参数定义.
#一般表示方法
my $a,$b;
sub max_num{
if($a > $b){
print "$a is the larger number";
}
else{
print "$b is the larger number";
}
}
#带参数表示方法
sub max_num{
if($_[0] > $_[1]){
print "$_[0] is the larger number";
}else{
print "$_[1] is the larger number";
}
}
子程序调用参数是参数会被存储在@_这个数组中,所以参数的第一个值存储在@_[0],第二个存储在@_[1]等依次类推
子程序中的多余参数会自动忽略,缺少的参数会用undef来表示。
子程序私有变量
- 默认情况下perl变量为全局变量
sub max_num{
my ($m,$n)=@_;
if($m > $n){
print "$m is the largest number";
}else{
print "$n is the largest number";
}
}
# result:6 is the largest number
HASH
- hash是key/value的集合
哈希赋值
整体赋值
-
%hash = ('jan' => 1,'feb' =>2,'mar' => 3 );
-
%hash = ('jan',1,'feb',2,'mar',3);
单独赋值
- $hash{'jan'} = first;
读取hash value
- $read_value = $hash{'key'};
delete hash key
- delete $hash{'key'};
获得hash key/value list
- @array_keys = keys(%hash);
- @array_value = values(%hash);
将hash value/key值赋予数组时,数组中的元素顺序可能总是不同的。
类UNIX操作
chdir
类似于linux cd command,directory要加双引号
chdir EXPR
change directory to EXPR;
#!/usr/bin/perl
chdir "/usr/home";
# Now you are in /usr/home dir.
chdir;
# Now you are in home directory /user/home/tutorialspoint
mkdir
mkdir EXPR,MODE
创建路径并加权限
#!/usr/bin/perl -w
$dirname ="/tmp/testdir";
mkdir $dirname, 0755;
opendir
readdir
system()
使用system()执行linux command,command需要加双引号
system("ln -sf dirs");
特殊参数
QA
-
Q:perl中的私有变量如何设定的?子程序中my ($a,$b)是私有变量,my $a,$b是私有变量吗?可以这样定义吗?
A:
-
代码块中{}内的变量都属于私有变量;
-
my $a,$b; 仅定义了$a;如果要全部定义,形式为my ($a,$b);
-
($a) = @_; #数组第一个元素赋值给$a; $a = @_; #$a为数组的个数;
-