当前位置:   article > 正文

perl脚本语言学习1——基础篇:变量、数组、哈希数组、循环、文件、函数

perl脚本


前言

2023.3.18 今天下载虚拟机把电脑磁盘内容弄到乱七八糟,难受
发现每次学习遇到一个坎,感觉面前是一座大山,越过去之后又对前途充满了希望


一、perl语言介绍

perl:practical extraction report language 实用提取和报表语言
从字面上看主要与文本处理相关

二、perl变量

变量定义关键词:my

1、标量 scalar

存储数字、字符、字符串,以$符号开头,一般不会特别在意是字符串、浮点数还是整数

my $money = 100000;
my $name = xxx;

my $old_year = $year;  //标量直接赋值给一个标量
  • 1
  • 2
  • 3
  • 4

1.1 数字

0377 八进制,以 0 开头
0xFF 十六进制,以 0x 开头
0b0000_1001 二进制,以 0b 开头

1.2 字符串

字符串用单引号双引号括起来。
单引号内不作转义,而双引号内转义
双引号字符串内可以内插其它标量,意单引号字符串中的$仅表示美元符,不会内插

"hello \n"  ---->hello  加回车
'hello \n'  ---->hello \n 直接输出
'a\'b'      ---->a'b  单引号内用'符号,要加转义符

my $a = "abc";
my $b = "def$a";  ---->$b = defabc
my $b = 'def$a';  ---->$b = def$a
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
1.2.1 字符串操作符

.:拼接操作符,"verdi" . "2016"
"#" x 40 :表示#重复 40 次
"-" x (40+5) :表示-重复 45 次

1.2.2 字符串函数

index(string,substring,skipchars):返回子串 substring 在字符串 string 中的位置
rindex(string,substring,skipchars):功能与 index()类似,不同的是它从 string 的右端开始查找

length(string):求字符串的长度

lc(string):把 string 中的所有字母都转换成小写字母
uc(string):把 string 中的所有字母都转换成大写字母
lcfirst(string):把 string 中的第一个字母转换成小写字母
ucfirst(string):把 string 中的第一个字母转换成大写字母

substr(string,skipchars,length):该函数在字符串 string 中跳过 skipchars 个字符的位置(从skipchars 位置处)开始抽取长度为 length 的子串。第一个字符的位置为 0
join(sepatorstring,list):把列表 list 中的所有元素串联到同一个字符串中,相邻两个元素之间使用 sepatorstring 分隔
sprintf(formatstring,field1,field2,...,fieldn):对字符串进行格式化,功能同 C 语言中的 sprintf()函数,不同的是该函数返回格式化后的结果字符串,就是有返回值

2、数组 array

定义:同一类标量的组合,以@符号开头
数组定义的同时就初始化

my @testcases = ("case0", "case1");
my @filelist = ();
$testcases[0]   //引用数组的第一个元素,下标从0开始

my @array = ();
$array[0] = "0";
$array[99] = "99";  //1-98的元素值为undef
$#array   //数组最后一个元素的索引值,比元素个数少1,例如上面例子就是99
my $array_size = $#array + 1;  //求出数组array的大小
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.1 数组函数

push:末尾增加一个元素
pop:取出数组末尾的元素
shift:取出数组开头的元素
unshfit:开头增加一个元素
sort:对数组排序
foreach:遍历

foreach my $e (@array){
	print "$e \n"
}    //依次换行输出数组里面的内容
  • 1
  • 2
  • 3

3、哈希数组 hash

定义:又称关联数组,以%符号开头,类似用字符串来索引的数组,像python的字典和sv中的关联数组。

3.1 数据拷贝

键Key => 值Value

my %dict = ("book" >= "UVM", "people" >= "xiaoli");
$dict{"book"}  //引用哈希数组索引book所对应的值
my $define_a_book = $dict{"book"};  //把book对应的值赋值给其他标量
  • 1
  • 2
  • 3

3.2 地址拷贝

在 C++里是&符号,在 Perl 里是\符号

my $arr_ref = \@arrs;  //得到数组地址给一个标量
my $hash_ref = \%hashs;
  • 1
  • 2

可以用@和%根据地址恢复出实际数组和哈希,也就是根据地址把数组和哈希数组的值重新赋值给一个新的数组和哈希数组tmp。

my @tmp = @$arr_ref;
my %tmp = %$hash_ref;
  • 1
  • 2

3、哈希数组函数

keys:返回所有关键字构成的数组
values:返回所有值构成的数组
exists :确定某个键 Key 是否存在
delete:用来删除某个键和值

my @mykey = keys %food;  
my @myvalue = values %food; 

foreach my $key (keys %food){
	print "$key: $mykey{$key}\n";  //一一对应输出哈希数组的内容
}

if(exsits $food{'apple'}){
	...
}

delete $food{'apple'};
%food = ();   //删除所有,只需要把它赋值为空哈希
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

三、控制流语句

1、if

if…
if…else…
if…elsif…else…
即使{}中的statement语句只有一条,{}也不能省略。当只有一条时也有一种简写方式。

if($cell_cnt > 0){
print "$cell_cnt";
}

statement if ();
print "$cell_cnt" if($cell_cnt > 0);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2、while

while( ){ }:先判断后执行
do{ } while():先执行后判断

my $i = 10;
while($i > 0){
	print "$i";
	$i--;
}    //输出10 9 8 .. 1

do{
	print "$i";
	$i--;
}while($i > 0);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3、for

for(initialization; test; increment){ }

for(my $i = 0; $i<10; $i++){
print "$i ";
}   //输出为0 1 ... 9
  • 1
  • 2
  • 3

4、foreach

前面已经介绍过了

5、循环退出

last:退出整个循环,相当于break
next:退出当前这次循环,相当于continue

for(my $i = 0; $i<10; $i++){
	if($i == 5)last;
	print "$i ";
}   //0 1 2 3 4 

for(my $i = 0; $i<10; $i++){
	if($i == 5)next;
	print "$i ";
}    //0 1 2 3 4 6 7 8 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

四、输入输出

1、键盘输入和显示屏输出

尖括号<>表示读入一行,<STDIN>表示从标准输入流中读取一行
STDOUT :表示输出的显示器(或终端界面)

my $line = <STDIN>;  //接收键盘输入得数据,直至回车
print STDOUT "hello";  //也可以不写STDOUT 
  • 1
  • 2

2、读写文件

2.1 打开文件

open(filehandle, mode, filename)filehandle 是文件句柄,相当于文件的指针,一般用大写字母命名;mode 定义了文件操作模式,如读写追加等;filename 是文件名,读的时候文件不存在则会报错,写的时候文件不存在则会自动创建。返回值:0 表示失败,1 表示成功。
die:当文件打开失败时就会输出错误信息,终止运行

open(FIN, "<", "123.txt") || die "can not open file, $!";  //FIN是文件句柄,不需要用my/$修饰
open(FIN, "<123.txt");  //也可以写成这种方式
  • 1
  • 2

2.2 移动读写指针

seek(filehandle, position, whence)whence 是三个值:0 表示文件一开头,1 表示当前位置,2 表示文件末尾;position 是相对于 whence 相对偏移字节数。
返回值:0 表示失败,1 表示成功。

seek(FIN, 54, 0);  //相对文件开头偏移54个字符
seek(FIN, -5, 2);  //相对文件末尾偏移5个字符,注意用负数
  • 1
  • 2

2.3 读取文件内容

undef:既不是数字0,也不是空的字符串,是一个标量,根据场合自动归为数字或字符串。
read(filehandle, $buffer, length):读取任意字节,$buffer 是一个标量,用来存放读取的数据;length 是要求读取的字节数;返回值是读取的实际字节数。如果读出错,则返回 undef

my $buf;
while(read(FIN, $buf, 1));   //每次读一个字节,直到文件最后

//读取文件一行的函数,文件句柄要加*号
my $line = readline(*FIN);
  • 1
  • 2
  • 3
  • 4
  • 5

2.4 写文件

print filehandle ("$buffer"):最常用的
printf filehandle ("format", arg1, arg2, ..., argN):printf也是常用的

print FOUT ("#buffer");
  • 1

write:一种写法和printf相同,另一种用法与select()函数搭配使用,可以省去 write 函数的 filehandle

select(FOUT);
write("num is %d\n", 50);
  • 1
  • 2

2.5 设当读写文件格式

binmode(filehandle):用来设定以二进制方式读写文件

2.6 使用范例

1、使用FIN,读取文件一行,配合 while 循环就可读取整个文件
$_:perl的内置变量,默认参数的意思,指的是在不指定的情况下,程序处理的上一个变量,在这里就是指的读取文件的一行

my $line = "";
while(<FIN>){
	$line .= $_;
}
  • 1
  • 2
  • 3
  • 4

2、使用FIN,一次性读取整个文件
$/:输入记录分隔符,默认是回车符\n,<>尖括号就是通过识别回车符读入一行。可以对其进行修改,但是建议是局部修改local,以免对其他地方产生影响。下面的代码将其局部定义为未定义的变量,所以$file变量就会一次性读取所有内容,因为没有分隔符了。

open(FIN, "<file.lst");
{
	local $/ = undef;   //{}限定在局部作用域,不影响全局的$/
	$file = <FIN>;
}
close(FIN);

//数组一次性读入文件
my @array = <FIN>;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

五、函数

sub来定义函数
@_:存储传递的实参
shift(@_):弹出第一个参数,数组元素-1,也可简写成 shift
返回值用关键字 return,如果没有关键字 return,函数会返回最后一个表达式的值。

sub add2 {
	my $para1 = shift(@_);
	my $para2 = shift(@_);
	my $ret = $para1 + $para2;
	return $ret;
}
my $val = add2(10,20);   //函数定义在前调用在后
my $val = &add2(10,20);  //函数调用在前定义在后
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
sub hello{
    my $f1 = "@_";  //取所有的参数组成一个字符串,各个参数用‘ ’隔开
    my $f2 = @_;    //取参数的个数, 等同于scalar(@_)
    my ($f3) = @_;  //取第一个参数的值, 等同于 $_[0],或者写成my $f3 = shift(@_);
    @w = @_;        //复制整个数组
    print "f1 is $f1\n";
    print "f2 is $f2\n";
    print "f3 is $f3\n";
}

hello(1,2,3);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
f1 is 1 2 3
f2 is 3
f3 is 1
  • 1
  • 2
  • 3

1、当需要传递数组给一个函数时,通常把数组的地址(指针)作为参数进行传递,用\符号,再在函数里面恢复数组

sub add_arrary {
	my $array_ref = shift;   //把数组指针给这个标量
	my @myarray = @$array_ref;   //根据地址还原出数组,用@符号
	my $ret = 0;
	foreach my $e (@myarray){
	$ret += $e; 
	}
	return $ret;
}
my @test_array = (1, 2 , 3 ,4, 5, 6, 7, 8, 9);
my $sum = add_array(\@test_array);  //传递的是数组的指针,用\符号
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2、函数变量的作用域
(1)一般只在函数内有效
(2)在子函数内部控制外面的变量,外面的变量就需要 local 定义
(3)在外面访问到子函数内部的变量,即变量不会在函数调用完后消失时,子函数内部的变量用 our 定义


练习题

1、perl脚本统计网表中cell类型和个数

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

my %cells = ();   //cell类型是字符串,所以要用哈希数组
open(FIN, "<digital_top_pr.v");
	my $line;
	while(<FIN>){
		if($_ = ~ m/\s+(\w+)\s(\w+)\s(\./) {   //这句没看懂,可能就是提取cell
			if(exits $cells{$1}){
				$cells{$1} += 1;
			}
			else{
				$cells{$1} = 1;
			}
	}
close(FIN);
foreach my $celltype (sort(keys %cells)){
	print "$celltype : $cells{$celltype}\n";
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

2、回归测试脚本

open和close要成对使用

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

open(CASE_LIST, "<tc.lst");
	my @tc = <CASE_LIST>;
close(CASE_LIST);

open(REPORT, "">report.rpt);
	foreach my $tc(@tc){
		chmop($tc);   //去除字符串行尾的换行符
		my $res = run_test($tc);
		if($res==0){
			print REPORT "$tc:PASS\n";
		}
		else{
				print REPORT "$tc:PASS\n"
			}
	}
close(REPORT);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/738296
推荐阅读
相关标签
  

闽ICP备14008679号