加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Perl笔记1

发布时间:2020-12-16 00:06:00 所属栏目:大数据 来源:网络整理
导读:1 标量数据: Perl用标量(scalar)来称呼单个事物。 (1)浮点数直接量:1.25 7.25e24 (2)整数直接量:12 -40 注:Perl里面允许你在整数直接量中插入下划线,将若干位数分开:54_5545_4966_6344 在这里不要使用逗号,因为逗号在 Perl里面已经有更重要的用途 (3)非

1 标量数据:
Perl用标量(scalar)来称呼单个事物。
(1)浮点数直接量:1.25 7.25e24
(2)整数直接量:12 -40
注:Perl里面允许你在整数直接量中插入下划线,将若干位数分开:54_5545_4966_6344
在这里不要使用逗号,因为逗号在 Perl里面已经有更重要的用途
(3)非十进制的整数直接量(也允许使用下划线)(前置零写法)
八进制直接量以0开头,十六进制直接量以0x开头,二进制直接量则以0b开头
0377 = 255
0xff = 255
0b22222111 = 255

2 字符串
Perl完全支持Unicode,但是需要手工加上utf8编译指令
use utf8;
(1) 单引号内的字符串直接量
除了单引号和反斜线字符外,单引号内所有字符都代表它们自己
单引号内的n并不是换行符,而是表示字面上的两个字符:反斜线和字母n
只有在反斜线后面接续单引号或者反斜线时,才表示转义

(2) 字符串操作符
连接符:.
"hello" . ' ' . "world"
字符串重复操作符:
小写字母x
"hello" x 3 hellohellohello
5? x 4.8 本质就是5 x 4 5555

"前置零"的技巧只对直接量有效,不能用于字符串的自动转换,自动转换总是按照十进制数字来处理的。
0377 = 255
'0377' 会转换成十进制数字377

3 Perl的内置警告信息
从Perl 5.6开始,我们可以通过编译指令开启警告功能
use warnings;
也可以在命令行使用-w选项对要运行的程序开启警告功能
perl -w 脚本文件

如果需要更加详细的问题描述,请使用
use diagnostics; --速度会变慢
注:告警不会改变程序的行为,只是抱怨几声而已

优化,通过perl的命令行选项-M来实现
perl -Mdiagnostics 脚本

4 标量变量
(1) 借助代码点创建字符
chr()函数:将字符的代码点转换成对应的字符
ord()函数:将字符转换为代码点

E 比较操作符
比较????????? 数字? 字符串
相等?????????? ==???? eq
不等?????????? !=???? ne
小于?????????? <????? lt
大于?????????? >????? gt
小于或等于???? <=???? le
大于或等于???? >=???? ge

特殊几个例子:
35 == 35.0 True
' ' gt ''? True
'35' == '35.0' False

F 布尔值
Perl里面其实没有专门的"布尔值"数据类型,规则如下:
如果是数字,0为假;所有其他数字都为真
如果是字符串,空字符串('')为假,所有其他字符串都为真
如果既不是数字也不是字符串,那就先转换成数字或者字符串再进行判断
注:字符串'0'跟数字0是同一个标量值,所以Perl会将字符串'0'唯一当成假的非空字符串。

5 获取用户输入

$line = <STDIN>;
if ($line eq "n")
{
? print "That was just a blank line!n";
}
else
{
? print "That line of input was: $line";
}

<STDIN>返回的字符串一般在末尾都会带有换行符。


6 chomp操作符
chomp() 只能作用于单个变量,且该变量的内容必须为字符串
如果该字符串末尾是换行符,chomp()的任务就是去掉它
常见用法:
chomp($text = <STDIN>);
chomp函数的返回值是实际移除的字符数。

$food = <STDIN>;
$betty = chomp $food; 可以不加括号

如果字符串后面有两个以上的换行符,chomp()仅仅删除一个,如果结尾没有它什么不做,返回零


7 undef值
在首次赋值前,变量的初始值就是特殊的undef(未定义)值,既不是数字也不是字符串。
其被当做数字时,作为0,当做字符时,当做空字符串。

8 defined函数
判断某个字符串是undef而不是空字符串,可以使用defined函数,如果是undef,该函数返回假,否则返回真
自己创建undef值
$madonna = undef;

9 列表和数组
列表指的是标量的有序集合,而数组则是存储列表的变量
$rocks[0] = 'Hello0';
$rocks[1] = 'Hello1';
$rocks[2] = 'Hello2';
$rocks[3] = 'Hello3';
$rocks[99] = 'Hello99';
数组最后一个元素的索引值是$#rocks
$end = $#rocks;
$number_of_rocks = $end + 1;
$rocks[$#rocks] = 'HelloLastValue'; #最后元素 或使用$rocks[-1]获取最后一个元素

列表直接量
(1,2,3)或(1,3,)或(1..3)或(1.7..3.7)
(5..1)空列表 只能向上计数
(1,5..9,12)
(0..$#rocks) #可以是表达式

列表时,可以使用qw,省去输入引号的繁琐
("hello1","hello2","hello3","hello4")
qw ( hello1 hello2 hello3 hello4 )

qw表示"quoted word"(加上单引号的单词)
除了用括号作为分隔符,Perl允许使用其他的定界符
qw ! hello1 hello2 hello3 hello4 !
qw / hello1 hello2 hello3 hello4 /
qw # hello1 hello2 hello3 hello4 #


列表赋值
($hello1,$hello2,$hello3,$hello4) = ("hello1","hello4");

交换变量
($hello1,$hello2) = ($hello2,$hello1);
($hello[0],$hello[1]) = ($hello[1],$hello[0]);

($hello1,$hello2) = qw / hello1 hello2 /;
引用整个数组时,使用@符号
@rocks = qw / hello1 hello2 hello3 hello4 /;

@copy1 = @copy2; # 将数组中的列表复制到另一个数组

10 POP和PUSH操作符
pop操作符负责取出数组中最后一个元素并将其作为返回值返回:
@array = 5..9;
$hello1 = pop(@array); #$hello1变成了9 @array = (5,6,7,8)
$hello2 = pop(@array);
如果数组是空的,pop什么也不做,直接返回undef.

push操作符负责向数组的尾端添加元素
push(@array,0);
push @array,8;

注:push和pop函数的第一个参数或唯一参数都必须是要操作的数组变量

11 shift和unshift操作符
此操作符是对数组的"开头"或最低下标值进行相应的处理

@arr = qw# dino fred barney #;
$m = shift(@arr); #$m变成"dino" @arr = qw# fred barney #;
$n = shift(@arr);
shift @arr; #@arr为空
$o = shift(@arr); #$o变成undef,@arr还是空
unshift(@arr,5); #@arr = (5)
unshift(@arr,4); #@arr = (4,5)
@others = 1..3;
unshift @arr,@others; #@arr = (1,4,5)
$i = 0;
while ($i<$#arr)
{
??? print $arr[$i];
??? print "n";
??? $i= $i + 1;

}

输出:
1
2
3
4

12 splice操作符
push-pop和shift-unshift操作符都是针对数组首尾操作的
splice可以接收四个参数,第一个参数是要操作的目标数组,第二个参数是要操作的一组元素的开始位置
如果只有两个参数,则Perl会把从给定位置开始一直到末尾的全部元素取出来并返回。
实例:
@array = qw( hello1 hello2 hello3 hello4 hello5 );
@removed = splice @array,2;
解释:
@removed = qw( hello3 hello4 hello5 );
@array = qw( hello1 hello2 );

通过第三个参数指定要操作的元素长度。
@array = qw( hello1 hello2 hello3 hello4 hello5 );
@removed = splice @array,1,2;
解释:
@removed = qw( hello2 hello3 );
@array = qw( hello1 hello4 hello5 );

第四个参数是要替换的列表
@array = qw( hello1 hello2 hello3 hello4 hello5 );
@removed = splice @array,qw( hello6); #在删除地方添加
解释:
@removed = qw( hello2 hello3 );
@array = qw( hello1 hello6 hello4 hello5 );

实际上,添加元素列表并不需要预先删除某些元素,把表示长度的第三个参数设为0,即可不加删除地插入新列表:
@array = qw( hello1 hello2 hello3 hello4 hello5 );
@removed = splice @array,qw( hello6);
解释:
@removed = qw( ); #没有删除任何元素
@array = qw( hello1 hello6 hello2 hello3 hello4 hello5 ); #Perl从索引位置1的地方插入新列表,然后顺移原来的元素


13 字符串中的数组内插
@array = qw( hello1 hello2 hello3 hello4 hello5 );
print "hello0 @array hellonn";
#@array会在数组的各个元素之间自动添加分隔用的空格
print @array; #如果不加双引号,则元素会靠在一起,元素之间没有空格

@hello = qw( hello1 hello2 hello3 hello4 );
$hello = "hello";
print "this is $hello[3]n";
print "this is ${hello}[3]n";
print "this is $hello" . "[3]n";
print "this is $hello[3]n";
输出结果为:
this is hello4
this is hello[3]
this is hello[3]
this is hello[3]


14 foreach 控制结构
foreach $hello (qw/ hello1 hello2 hello3 /) #控制变量:$hello
{
??? print "One Hello? is $hello.n";
}

输出:
One Hello is hello1.
One Hello is hello2.
One Hello is hello3.

控制变量并不是列表元素的复制品,实际上,它是列表元素本身。
假如修改了控制变量的值,也就同时修改了这个列表的值
@hellos = qw/ hello1 hello2 hello3 /;
print "The hellos are:n",@hellos,"n";
foreach $hello (@hellos)
{
??? $hello = "t$hello";
??? $hello .= "n";
}

print "The hellos are:n",@hellos;

输出:
The hellos are:
hello1hello2hello3
The hellos are:
?hello1
?hello2
?hello3

当循环结束后,控制变量的值会变成什么,看下面的例子:
$hello = "GOODBOY";
@hellos = qw/ hello1 hello2 hello3 /;
foreach $hello (@hellos)
{
??? $hello = "t$hello";
??? $hello .= "n";
}

print "The hello value is still $hellon";

结果:
The hello value is still GOODBOY
控制变量的值恢复到之前的值。

15 Perl的默认变量: $_
foreach (1..5)
{
??? print "I can count to $_!n";
}

输出:
I can count to 1!
I can count to 2!
I can count to 3!
I can count to 4!
I can count to 5!

当未告知Perl使用哪个变量或数值时,Perl会自动使用$_
$_ = "hellon";
print ;默认打印$_的值

16 reverse操作符
读取列表(或数组)的值,并按照相反的次序返回该列表。
@hello = 6..10;
@hello = reverse(@hello);

@hello = reverse 6..10;

reverse操作符不会修改传进来的参数。

17 sort操作符
读取列表(或数组)的值,并按照内部的字符编码顺序对它们进行排序。
@hellos = qw/ hello1 hello2 hello3 /;
@hellos = sort(@hellos);

@hellos = sort @hellos;


18 each操作符
从Perl 5.12版本开始,已经可以针对数组使用each操作符了。但是在此之前,each只能用于提取哈希的键-值。
每次对数组调用each,会返回数组中下一个元素所对应的两个值-该元素的索引以及该元素的值。

use 5.012;
my @hellos = qw/ hello1 hello2 hello3 hello4 /;
while ( my( $index,$value ) = each @hellos )
{
??? say "$index: $value";
}

如果不用each来实现,就得按照自己根据索引从小到大依次遍历,然后借助索引值获取元素的值
@hellos = qw/ hello1 hello2 hello3 hello4 /;
foreach $index (0..$#hellos)
{
??? print "$index: $hellos[$index]n";
}

结果:
0: hello1
1: hello2
2: hello3
3: hello4


19 标量上下文和列表上下文
@people = qw( fred barney betty );
@sorted = sort @people; #列表上下文:fred,barney,betty
$number = 42 + @people; #标量上下文:42 + 3? 得45

@list = @people; #得到三个元素的列表
$n = @people; #得到元素个数3

(1) 在标量上下文中使用产生列表的表达式
sort在标量上下文中总是返回undef;
reverse在列表上下文中自然地返回逆序后的列表
而在标量上下文中则返回逆序后的字符串
@backwards = reverse qw/ yabba dabba doo /; #得到doo,dabba,yabba
$backwards = reverse qw/ yabba dabba doo /; #得到oodabbadabbay

(2) 在列表上下文中使用产生标量的表达式
@hello = undef; #结果得到一个列表,而且仅有一个元素为未定义 undef是标量值,所以不会清空该数组
@hello =( ); # 这才是正确的清空数组的方法,和上面的做法完全不同

(3) 强制指定列表上下文
伪函数scalar
@rocks = qw( hello1 hello2 hello3 hello4 );
print "How many rocks do you have?n";
print "I have ",@rocks," rocks!n"; #会输出列表的全部内容
print "I have ",scalar @rocks," rocks!n"; # 正确输出列表中元素的个数

输出:
How many rocks do you have?
I have hello1hello2hello3hello4 rocks!
I have 4 rocks!

注:不需要相应的函数用来强行切入到列表上下文,用不到这个需求
@hello = <STDIN>; #将输入的多行元素放到@hello数组中 退出输入后使用CTRL+D
chomp(@hello); #去掉每行末尾的回车符n

比较好的写法是:
chomp(@hello = <STDIN>);

实例:
@hello = qw( fred betty barney dino wilma pebbles bamm-bamm );
chomp(@number = <STDIN>);
foreach (@number)
{
??? print "$hello[$_ - 1]n";
???
}

测试:
[root@etl10 scott]# perl test.pl? #输入1 6 5 7后按CTRL+D
1?????
6
5
7
fred
pebbles
wilma
bamm-bamm

20 子程序
sub定义子程序

sub marine
{
??? $n += 1;
??? print "Hello,sailor number $n!n";
}
marine; #也可以写成&marine,对marine子程序的调用
marine; #也可以写成&marine,对marine子程序的调用
输出:
Hello,sailor number 1!
Hello,sailor number 2!
Hello,sailor number 3!

(1) 子程序的返回值
测试1:
$fred = 2;
$barney = 12;
sub marine
{
??? $fred + $barney;
}
$return_value = marine;
print "$return_valuen";

输出:
14

测试2:
$fred = 2;
$barney = 12;
sub marine
{
??? $fred + $barney;
??? print "Hello,sub marinen"; #多添加了一句print打印输出
}

$return_value = marine;
print "$return_valuen";

输出:
1? #表示子程序正常执行,成功输出信息

(2) 传入参数
测试1:
#!/usr/bin/env perl
sub max
{
??? if ($_[0] > $_[1]) #$_[0]代码传入的第一个参数,$_[1]代表传入的第二个参数,以此类推
??? {
??????? $_[0];
??? }
??? else
??? {
??????? $_[1];
??? }
}
chomp($one = <STDIN>);
chomp($two = <STDIN>);
$return_max_value = max($one,$two);
print "$return_max_valuen";

测试结果:
[root@etl10 scott]# perl test.pl
12
34
34 #输出最大值
[root@etl10 scott]# perl test.pl
34
2
34 #输出最大值
[root@etl10 scott]# perl test.pl
2
2
2 #输出最大值

但是这不是最好的方法,里面$_[0],$_[1]......不太好

(3) 子程序中的私有变量
?默认情况下,Perl里面的所有变量都是全局变量
?但是可以利用my操作符来创建私有变量(词法变量 lexical variable)
sub max
{
??? my($m,$n); #定义私有变量
??? ($m,$n) = @_; #将参数赋值给变量
??? if ($m > $n)
??? {
??????? $m; #;是可以省略的 Perl允许省略语句块中最后一个分号,当且仅当代码块只有一行
??? }
??? else
??? {
??????? $n; #;是可以省略的 Perl允许省略语句块中最后一个分号,当且仅当代码块只有一行
??? }
}

注:
my($m,$n); #定义私有变量
($m,$n) = @_; #将参数赋值给变量
这两行可以写成:
my($m,$n) = @_;


(4) 变长参数列表
对参数个数进行校验:
sub max
{
??? if (@_ != 2)
??? {
??????? print "WARNING! $max should get exactly two arguments!n";
??? }
??? my($m,$n);
??? ($m,$n) = @_;
??? if ($m > $n)
??? {
??????? $m
??? }
??? else
??? {
??????? $n
??? }
}
?

接收任意参数的程序:
$maximum = &max(2,5,9,12);
sub max
{
??? my($max_so_far) = shift @_; # 数组中的第一个值,暂时设为最大值
??? foreach (@_)??????????????? #遍历数组@_中的其他元素
??? {
??????? if ($_ > $max_so_far)
??????? {
??????????? $max_so_far = $_;
??????? }
??? }
???
??? $max_so_far;
}
print "$maximumn";

输出:
12

空参数列表:
@hello = ( ); # @hello为空的数组
$maximum = &max(@hello);
sub max
{
??? my($max_so_far) = shift @_; # 数组中的第一个值,为undef
??? foreach (@_)??????????????? #遍历数组@_中的其他元素,因为数组为空的,所有循环不执行
??? {
??????? if ($_ > $max_so_far)
??????? {
??????????? $max_so_far = $_;
??????? }
??? }
???
??? $max_so_far;
}
print "$maximumn";

(5) 词法变量(my)
my操作符并不会更改变量赋值时的上下文:
my($num) = @_; #列表上下文,和 ($num) = @_;相同 $num被设置为第一个参数
my $num = @_; #标量上下文,和 $num = @_;相同$num被设置为参数的个数

测试:
print "$maximumn";
@hellos = qw(hello faf afaf faf);
my($num) = @hellos;
print "$numn";
my $num = @hellos;
print "$numn";

输出:
hello
4

在my操作符不加括号时,只能用来声明单个词法变量:
my $hello1,$hello2; #错误,只声明了$hello1
my($hello1,$hello2);

在日常Perl编程中,最好新的变量都使用my声明,保持在自己的作用域中
foreach my $rock (qw/ hello1 hello2 hello3 /)
{
??? print "One rock is $rock.n";
}???

(6) use strict编译指令
use strict; #强制使用一些严格的,良好的编程风格
从Perl 5.12开始,如果使用编译指令指定最低Perl版本号的话,就相当于隐式打开了约束指令
use 5.012; #自动加载strict指令

(7) return操作符
#!/usr/bin/env perl
my @names = qw/ hello1 hello2 hello3 /;
my $result = &which_element_is("hello3",@names);
print "$resultn";

sub which_element_is
{
??? my($what,@array) = @_;
??? foreach (0..$#array)
??? {
??????? if ($what eq $array[$_]) #字符相等比较符eq,数字相等比较符==
??????? {
??????????? return $_;
??????? }
??? }
??? -1;
}

结果为:
3? # hello3位于数组的第三个元素(序列为3)

(8) 省略与号
如果编译器在调用子程序前看到过子程序的定义,或者Perl通过语法规则判断它只能是子程序调用,
那么对待该子程序就可以像内置函数那样,在调用时省略与号。
my @cards = shuffle(@desk_of_cards); #shuffle上的&是多余的 将参数列表放进括号里面,就一定是函数


或者,如果Perl的内部编译器已经见过子程序的定义,通常也可以省略与号
sub division
{
??? $_[0] = $_[0];
}
my $quotient = division 355,113;???

例外:假如这个子程序和Perl内置函数同名,就必须使用与号调用,避免歧义。


(9) 持久化私有变量
state来声明变量,该变量属于当前子程序的私有变量,并且在多次调用这个子程序期间保留该变量的值
测试1:
use 5.010; # 引入该特性
sub marine
{
??? state $n = 0;
??? $n += 1;
??? print "Hello,sailor number $n!n";
}

输出:
Hello,sailor number 2!

测试2:
use 5.010; # 引入该特性
&marine;
&marine;
sub marine
{
??? $n = 0;
??? $n += 1;
??? print "Hello,sailor number $n!n";
}
输出:
Hello,sailor number 1!

类似标量变量,其他任意类型的变量都可以被声明为state变量
#!/usr/bin/env perl
use 5.010;
running_sum(5,6);
running_sum(1..3);
running_sum(4);

sub running_sum
{
??? state $sum = 0;
??? state @numbers;
??? foreach my $number (@_) # 接收传入的值
??? {
??????? push @numbers,$number;
??????? $sum += $number;
??? }
??? say "The sum of (@numbers) is $sum.";
}

输出:
The sum of (5 6) is 11.
The sum of (5 6 1 2 3) is 17.
The sum of (5 6 1 2 3 4) is 21.

特别注意:
在使用数组和哈希类型的state变量时,还是有一些轻微的限制的。
在Perl 5.10中我们不能在列表上下文初始化这两种类型的state变量
state @array = qw/ a b c /;
#错误
Initialization of state variables in list context currently forbidden
到5.14还是无法使用


实例:
sub total
{
??? my $sum = 0;
??? foreach (@_)
??? {
??????? $sum += $_;
??? }
??? return $sum;
}
my $result = total(1..100);
print "Result is :$resultn";


实例:
#!/usr/bin/env perl
use 5.010;
sub greet
{
??? state @people_lists;
??? state @people_before;
??? push @people_lists,@_;
??? if ($#people_lists == 0)
??? {
??????? print "Hello ",@_,",you are the first one!n";
??? }
??? elsif ($#people_lists == 1)
??? {
??????? print "Hello ",you are the second one!n";
??? }
??? else
??? {
??????? print "Hello ",There are [@people_before] before you!n";
??? }
???
??? push @people_before,@_;

}

greet("CAT");
greet("DOG");
greet("PIG");
greet("APPLE");
greet("ORANGE");

输出:
Hello CAT,you are the first one!? #第一位客户
Hello DOG,you are the second one! #第二位客户
Hello PIG,There are [CAT DOG] before you! #第三位,同时输出他前面还有几位
Hello APPLE,There are [CAT DOG PIG] before you!
Hello ORANGE,There are [CAT DOG PIG APPLE] before you!

实例2:
use 5.010;
greet('CAT');
greet('DOG');
greet('PIG');
greet('APPLE');
sub greet
{
??? state @names;
??? my $name = shift;
??? print "Hi $name! ";
??? if (@names)
??? {
??????? print "I've seen: @namesn";
??? }
??? else
??? {
??????? print "You are the first one here!n";
??? }
???
??? push @names,$name;
}

输出: Hi CAT! You are the first one here! Hi DOG! I've seen: CAT Hi PIG! I've seen: CAT DOG Hi APPLE! I've seen: CAT DOG PIG

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读