简介

什么是Perl语言?

Perl一般被称为“实用报表提取语言”( Practical Extraction and Report Language)
Perl最初的设计者为拉里沃尔(Larry Wall)他于1987年12月18日发表。
“Perl”,有大写的P,是指语言本身;"perl”,小写的p,是指程序运行的解释器。

Perl语言特点

1、开源免费

2、支持跨平台

3、直接运行,无需复杂编译

4、内部集成正则表达式

5、CPAN模块库

为什么Perl语言适合处理生物数据

1、正则表达是善于处理字符串

2、脚本语言,善于批量化和流程化

3、很多生物学软件用Perl语言编写

4、简单易学

基础语法

Perl 程序有声明与语句组成,程序自上而下执行,包含了循环,条件控制,每个语句以分号 (;) 结束。
Perl 语言没有严格的格式规范,你可以根据自己喜欢的风格来缩进。

单引号和双引号

1
2
3
4
5
#!/usr/bin/perl

print "Hello, world\n"; # 双引号
print 'Hello, world\n'; # 单引号

输出结果如下:

Hello, world Hello, world\n
从结果中我们可以看出,双引号 \n 输出了换行,而单引号没有。
Perl双引号和单引号的区别:
(1)双中有双,单中有单都需要 \ 转义。

(2)双中有单或单中有双均不需要转义。

(3)单引号直接了当,引号内是什么就显示什么,双引号则需要考虑转义或变量替换等。双引号可以正常解析一些转义字符与变量,而单引号无法解析会原样输出。

Perl 数据类型

Perl语言中数组主要有 标量 数组 哈希

  1. 标量
    标量是 Perl 语言中最简单的一种数据类型。这种数据类型的变量可以是数字,字符串,浮点数,不作严格的区分。在使用时在变量的名字前面加上一个 $,表示是标量。
    例如:
    $myfirst=123;  #数字123  $mysecond="123"; #字符串123 

  2. 数组
    数组变量以字符 @ 开头,索引从 0 开始,如:@arr=(1,2,3)

  3. 哈希
    哈希是一个无序的 key/value 对集合。可以使用键作为下标获取值。哈希变量以字符 % 开头。
    eg%h=('a'=>1,'b'=>2);

转义字符

转义字符 含义
\\ 反斜线
\' 单引号
\" 双引号
\a 系统响铃
\b 退格
\f 换页符
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\0nn 创建八进制格式的数字
\xnn 创建十六进制格式的数字
\cX 控制字符,x可以是任何字符
\u 强制下一个字符为大写
\l 强制下一个字符为小写
\U 强制将所有字符转换为大写
\L 强制将所有的字符转换为小写
\Q 将到\E为止的非单词(non-word)字符加上反斜线
\E 结束\L、\U、\Q

标量

标量是一个简单的数据单元。

标量可以是一个整数,浮点数,字符,字符串,段落或者一个完整的网页。

以下实例演示了标量的简单应用:

1
2
3
4
5
6
7
8
9
#!/usr/bin/perl

$age = 20; # 整数赋值
$name = "Runoob"; # 字符串
$salary = 130.50; # 浮点数

print "Age = $age\n";
print "Name = $name\n";
print "Salary = $salary\n";

执行以上程序,输出结果为:

Age = 20 Name = Runoob Salary = 130.5

1、Perl中最基本的数据类型
2、可以是数字、字母
3、无需定义类型
4、“单数”为标量

直接量

在程序中直接定义一个值,就叫做直接量。
1e-5
-40
“Hello,world”
print"2.4+3"
1 000 100

数字操作符

加2+3
减5.1-2.4
乘3*12
除14/2(除数不能为0)
取模10%3
乘幂 2**3

字符串运算

1、所谓字符串就是一连串的字符组合,字符可以是字母,也可以是数字,包括标点等;
2、对DNA序列处理本质上就是处理字符串;3、字符串可以为空
4、需要“引号”

”序列”字符串处理

序列也是字符串
ATGAATCCAAATCAGAAGATAACAGCAATTGGCTCTGTTTCTCTAATCATTGCGATAATATGTCTCCTCATGCAAATTGCCATCTTAACAACGACTATGACATTACAATTCTGGCAGAAAGAATGCAGTAACCCATCGAATAATCAAGTGATGCCATGTGAACCGATCATAATAGAA
计算长度反向
碱基互补配对替换
截取
翻译成氨基酸

单引号与双引号字符串的差别

  1. 单引号内的内容表示内容本身(单引号和反斜线除外);

  2. 单引号内表示单引号和反斜线需要转意;
    Print ‘she said that:’ hello,world’

  3. 双引号支持反斜线转意;
    例:print’hello , world!\n’
    print"hello , world !\n"

字符串操作符

字符串连接
使用. : "hello ". “world”

使用x : “fred” x 3

5x4=20?或者5555?
54
“Z”. 5
7

标量变量

标量变量用美元$表示
变量的命名规范
1、不能以数字开头$100
2、可以以字母下划线开头,后面可以有数字
3、严格区分大小写
4、命名最好与变量用途相关,不要过短
5、不要采用内部保留变量名 (eg NRGV;NRGV;ENV…)

变量赋值

1
2
3
4
5
6
$dna="ATTTTTTGC";
$gene_num=3;
$gene_num=$gene_num+4;
$gene_num+=4; #为上一行的简写
$dna.= "ATTTCCGCTC”; #.=用于字符串链接
ATTTTTTGCATTTCCGCTC

(注意:这里的=不代表数学意义上的等于,而是赋值的意思;==才代表数学意义上的等于)

操作符(运算符)优先级

2+3*4结果等于14,
genenum=gene_num=gene_num+4;
(2+3)*4结果等于20,


运算符符 结合性 描述
++, – 自增,自减
-, ~, ! 从右到左 单目
** 从右到左 乘方
=~, !~ 从左到右 模式匹配
*, /, %, x 从左到右 乘,除,取余,重复
+, -, . 从左到右 加,减,联接
<<, >> 从左到右 移位
-e, -r, 文件状态
<, <=, >, >=, lt, le, gt, ge 从左到右 不等比较
==, !=, <=>, eq, ne, cmp 从左到右 相等比较
& 从左到右 位与
, ^ 从左到右 位或,位异或
&& 从左到右 逻辑与
从左到右
从左到右 列表范围
? and : 从右到左 条件操作符
=, +=, -=, *=, 从右到左 赋值
其他
, 从左到右 逗号操作符
not 从左到右 Low-precedence logical NOT
and 从左到右 lLow-precedence logical AND
or, xor 从左到右 lLow-precedence logical OR and XOR

比较运算符

表格实例中设置变量 $a 为 10, $b 为 20。

运算符 描述 实例
== 检查两个操作数的值是否相等,如果相等则条件为 true,否则为 false。 ($a == $b) 为 false
!= 检查两个操作数的值是否相等,如果不相等则条件为 true,否则为 false。 ($a != $b) 为 true。
<=> 检查两个操作数的值是否相等, 如果左边的数小于右边的数返回 -1,如果相等返回 0, 如果左边的数大于右边的数返回 1 。 ($a <=> $b) 返回 -1。
> 检查左操作数的值是否大于右操作数的值,如果是则条件为 true,否则为 false。 ($a > $b) 返回 false。
< 检查左操作数的值是否小于右操作数的值,如果是则条件为 true,否则返回 false。 ($a < $b) 返回 true。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为 true,否则返回 false。 ($a >= $b) 返回 false。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为 true,否则返回 false。。 ($a <= $b) 返回 true.

换行符

回车和换行

在linux系统下是换行\n;
在mac系统下是回车\r;
windows系统下回车加换行两个字符\r\n;

不同系统之间换行符的转换

dos2unixwindows转换为linux
unix2dos:linux转换为windows
unix2mac :linux转换为mac
mac2unix:mac转换为linux

chomp函数

功能:去除换行符
test= "hello,world\n' chomp (test);# “hello,world”
chomp (test);# "hello,world" chomp (test);# “hello,world”
chomp ($test);# “hello,world”

chop函数

功能:每输入一次就会去掉后面一个字符

1
2
3
4
5
6
$test= "hello,world\n
chop ($test); # "hello,world";
chop ($test); # "hello,worl";
chop ($test); # "hello,wor";
chop ($test); # "hello,wo";
chop ($test); # "hello,w";

列表和数组

列表(list)指的是标量的有序集合
数组(array)则是存储列表的变量。
@array=[1,2,3,4,5];
@array=[1, “hello”,undef, $dna,5];

数组的访问

@array=[1,2,3,4,5];
array[0]=1;array[0]=1; array[1]=2;
array[2]=3;array[2]=3; array[3]=4;
array[4]=5;......array[4]=5; ...... array[99]=100;

数组的元素个数

@array=[1,2,3,4,5];
数组最后一个元素角标#array; 数组元素个数=#array+1;

构建列表

  1. 括号,元素之间用逗号隔开;
    (1,2,3,4,5)

  2. 范围操作符(…)每次加一
    @number=(1..100); print "@number\n";

  3. qw操作符,可以省略逗号
    @strings=qw (fred barney betty wilma dino); @stringl=qw !fred barney betty wilma dino!; @string2= #fred barney betty wilma dino#; @string3=qw /fred barney betty wilma dino/; @string4=qw {fred barney betty wilma dino}; dstring5=qw <fred barney betty wilma dino>;

数组赋值

eg

1
2
3
4
(Sfred, Sbarney, Sdino)=("flintstone","rubble", undef);
print "Sfred\n";
print "$barney\n";
print "$dino\n";

output:
flintstone
rubble

split和join

split将字符串根据固定的分隔符进行切割,切割后得到一个数组;

1
2
3
4
5
6
7
8
9
#!/usr/bin/perl

$scalar="abc:def:g:h";
@array=split /:/,$scalar;
print "@array\n";


perl *.pl
abc def g h

join与split刚好相反,它的作用是将数组连接成一个标量

1
2
3
4
5
6
$new_scalar=join ":",@array;

print "$new_scalar\n";

perl *.perl
abc:def:g:h

Perl帮助文档

通过访问perl官方文档
在linux系统下 输入 perldoc 即可

1
2
3
4
5
6
7
8
9
10
11
12
perldoc -f chomp #查找函数的功能
perldoc -m Data::Dumper #直接查看模块代码
perlodc -q regex #搜寻含此关键字的文档
perldoc -v @ARGV #查询内置变量
perldoc -o LaTex -d texttrap.docs Text::Wrap # 将Text::Wrap模块的帮助信息,以LaTex格式输出到文件中
perldoc File::Basename #直接进入到模块的详情页
-l 查看perl模块安装路径
-T 直接输出到屏幕
#帮助手册
perldoc perlfaq
perldoc perlfaq3
perldoc perlsyn

语法手册


手册页 内容
perl 有些什么 perl 手册页
perldata 数据类型
perlsyn 语法
perlop 操作符和优先级
perlre 正则表达式
perlvar 预定义变量
perlsub 子过程
prelfunc 内建函数
perlmod 如何令 Perl 模块工作
perlref 参考手册
perlobj 对象
perlipc 进程间通讯
perlrun 如何运行 Perl 命令,以及命令行开关
perldebug 调试
perldiag 诊断信息

faq手册


手册页 内容
perlfaq1 关于 Perl 的通用信息
perlfaq2 获取和学习 Perl
perlfaq3 编程工具
perlfaq4 数据操作
perlfaq5 文件和格式
perlfaq6 正则表达式
perlfaq7 通用 Perl 语言信息
perlfaq8 系统交互
perlfaq9 网络

移植相关手册


手册页 内容
perlamiga Amiga 移植
perlcygwin Cygwin 移植
perldos MS-DOS 移植
perlhpux HP-UX 移植
perlmachten Power MachTen? 移植
perlos2 OS/2 移植
perlos390 OS/390 移植
perlvms DEC VMS 移植
perlwin32 MS-Windows 移植

在平时编程中要熟练查看帮助文档

输入与输出

open函数文件读写

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl -w
use strict;

open IN,"<gene.ffn";
open OU,">protein.faa";
open OU,">>protein.faa"; # 追加到文件内容后面,和linux重定向一个意思
#首先是open函数打开文件;
#IN或OU称为文件句柄,就是程序里代表Perl进程与外界之间IO联系的名字,也就是联系的名称(句柄可以理解成)
#逗号分隔
# '>','<'输入输出方向
# 文件路径

文件句柄

在文件I/O中,要从一个文件读取数据,应用程序首先要调用操作系统函数并传送文件名,并选一个到该文件的路径来打开文件。该函数取回一个顺序号,即Perl文件句柄(filehandle)
文件句柄用来对应要操作的文件系统中的文件,这么说不太严谨,但比较容易理解。首先为要打开的文件绑定文件句柄(称为打开文件句柄),然后在后续的操作中都通过文件句柄来操作对应的文件,最后关闭文件句柄。

perl保留文件句柄
STDIN, STDOUT, STDERR,DATA,ARGV和ARGVOUT
标准输入,标准输出,错误输出

@ARGV

perl cds2pep.pl gene.ffn protein.faa 1
cds2pep.pl $O
gene.ffn: $ARGV[0] 命令行第1个参数
protein.faa: $ARGV[1]命令行第二个参数
1: $ARGV[2]命令行第三个参数

1
2
3
4
5
6
7
8
!/usr/bin/perl -w
use warnings;

open IN,"<$ARGV[0]",or die"can not open the file\n$!";
print "\$0 is $0\n";
print "\$ARGV[O] is $ARGV[0]\n";
print "\$ARGV[1] is $ARGV[1]\n";
print "\$ARGV[2] is $ARGV[2]\n";

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/usr/bin/perl -w

open IN,"<$ARGV[0]";
$First=<IN>;
$Second=<IN>;
$Third=<IN>;
$Forth=<IN>;
$Fifth=<IN>;
print"$First\n$Second\n$Third\n$Forth\n$Fifth\n";


#!/usr/bin/perl -w

open IN,"<$ARGV[0]";
$/=">"; #以'>'进行分割
<IN>;
$First=<IN>;
print "$First\n";
# 每次读取一个字段赋值给一个标量太麻烦,正常情况下将文件句柄使用在while循环中


# while循环

#!/usr/bin/perl -w

open IN,"<$ARGV[0]";

while (<IN>) {
print "$_";
}

#或者赋值给$line
while ($line=<IN>) {
print "$line";
}


# 不会输出到屏幕而是输入到创建的文件中
#!/usr/bin/perl -w

open IN,"<$ARGV[0]"; #'<'符号可以省略
open OU,"$ARGV[1]";

while (<IN>) {
print "$_";
}
close IN;
close OU; # close函数关闭文件句柄

格式转换程序

fastq转fasta

首先两个文件差别在于 fasta文件为四行,fastq为两行
fasta为>开头,fastq为@开头

1
2
3
4
5
6
7
8
9
#fastq格式文件
@FCD056DACXX:3:1101:2163:1959#TCGCCGTG/1
TCCGATAACGCTCAACCAGAGGGCTGCCAGCTCCGATCGGCAGTTGCAACCCATTGGCCGTCTGAGCCAGCAACCCCGGA
+
gggiiiiiiiiiiiiiiiiiiiiiiiiiigggggeeecccccc^bcbcccccccbccccc]aaccbbccc^R^^acccc_

#fasta格式文件
>FCD056DACXX:3:1101:2163:1959#TCGCCGTG/1
TCCGATAACGCTCAACCAGAGGGCTGCCAGCTCCGATCGGCAGTTGCAACCCATTGGCCGTCTGAGCCAGCAACCCCGGA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/perl -w

open IN,"zcat $ARGV[0] |";
open OU,">$ARGV[1]";

while ($id=<IN>) {
chomp ($id);
chomp ($seq=<IN>);
<IN>;
<IN>;
$id=~ tr /@/>/;
print OU "$id\n";
print OU "$seq\n";
}

close IN;
close OU;

=~将左边的值交给右边做匹配,并直接修改左边的值;相当于shell的-i 's////g'

哈希

哈希是 key/value 对的集合。
Perl中哈希变量以百分号 (%) 标记开始。

访问哈希元素

访问哈希元素格式:${key}。
以下是一个简单的哈希实例:

1
2
3
4
5
6
7
#!/usr/bin/perl

%data = ('google', 'google.com', 'runoob', 'runoob.com', 'taobao', 'taobao.com');

print "\$data{'google'} = $data{'google'}\n";
print "\$data{'runoob'} = $data{'runoob'}\n";
print "\$data{'taobao'} = $data{'taobao'}\n";

创建哈希

创建哈希可以通过以下两种方式:

  1. 为每个 key 设置 value
1
2
3
$data{'google'} = 'google.com';
$data{'runoob'} = 'runoob.com';
$data{'taobao'} = 'taobao.com';
  1. 通过列表设置
    列表中第一个元素为 key,第二个为 value。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
%data = ('google', 'google.com', 'runoob', 'runoob.com', 'taobao', 'taobao.com');

# 也可以使用 => 符号来设置 key/value:
%data = ('google'=>'google.com', 'runoob'=>'runoob.com', 'taobao'=>'taobao.com');

# 以下实例是上面实例的变种,使用 - 来代替引号:
%data = (
-google=>'google.com',
-runoob=>'runoob.com',
-taobao=>'taobao.com',
);

# 使用这种方式 key 不能出现空格,读取元素方式为:
$val = $data{-google}
$val = $data{-runoob}

读取哈希值

哈希值提取到数组语法格式:@{key1,key2}。

1
2
3
4
5
6
7
#!/uer/bin/perl

%data = (-taobao => 45, -google => 30, -runoob => 40);

@array = @data{-taobao, -runoob};

print "Array : @array\n";

执行以上程序,输出结果为:Array : 45 40

读取哈希的 key 和 value

读取所有key

可以使用 keys 函数读取哈希所有的键,语法格式如下:keys %HASH

eg

1
2
3
4
5
6
7
8
9
#!/usr/bin/perl 

%data = ('google'=>'google.com', 'runoob'=>'runoob.com', 'taobao'=>'taobao.com');

@names = keys %data;

print "$names[0]\n";
print "$names[1]\n";
print "$names[2]\n";

输出结果为:

1
2
3
google
runoob
taobao

类似的可以使用 values 函数来读取哈希所有的值,语法格式如下:values %HASH
该函数返回所有哈希的所有 value 的数组。

1
2
3
4
5
6
7
8
9
#!/usr/bin/perl 

%data = ('google'=>'google.com', 'runoob'=>'runoob.com', 'taobao'=>'taobao.com');

@urls = values %data;

print "$urls[0]\n";
print "$urls[1]\n";
print "$urls[2]\n";

输出结果为:

1
2
3
google.com
runoob.com
taobao.com

检测元素是否存在

在哈希中读取不存在的 key/value 对 ,会返回 undefined 值,且在执行时会有警告提醒。
为了避免这种情况,可以使用 exists 函数来判断key是否存在,存在的时候读取:

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl

%data = ('google'=>'google.com', 'runoob'=>'runoob.com', 'taobao'=>'taobao.com');

if( exists($data{'facebook'} ) ){
print "facebook 的网址为 $data{'facebook'} \n";
}
else
{
print "facebook 键不存在\n";
}

获取哈希大小

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl

%data = ('google'=>'google.com', 'runoob'=>'runoob.com', 'taobao'=>'taobao.com');

@keys = keys %data;
$size = @keys;
print "1 - 哈希大小: $size\n";

@values = values %data;
$size = @values;
print "2 - 哈希大小: $size\n";

输出结果为:
1 - 哈希大小: 3 2 - 哈希大小: 3

哈希中添加或删除元素

添加 key/value 对可以通过简单的赋值来完成。但是删除哈希元素你需要使用 delete 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/perl

%data = ('google'=>'google.com', 'runoob'=>'runoob.com', 'taobao'=>'taobao.com');
@keys = keys %data;
$size = @keys;
print "1 - 哈希大小: $size\n";

# 添加元素
$data{'facebook'} = 'facebook.com';
@keys = keys %data;
$size = @keys;
print "2 - 哈希大小: $size\n";

# 删除哈希中的元素
delete $data{'taobao'};
@keys = keys %data;
$size = @keys;
print "3 - 哈希大小: $size\n";

输出结果为:
1 - 哈希大小: 3 2 - 哈希大小: 4 3 - 哈希大小: 3

迭代哈希

可以使用 foreach 和 while 来迭代哈希:

使用 foreach

1
2
3
4
5
6
#!/usr/bin/perl

%data = ('google'=>'google.com', 'runoob'=>'runoob.com', 'taobao'=>'taobao.com');
foreach $key (keys %data){
print "$data{$key}\n";
}

使用 while

1
2
3
4
5
6
#!/usr/bin/perl

%data = ('google'=>'google.com', 'runoob'=>'runoob.com', 'taobao'=>'taobao.com');
while(($key, $value) = each(%data)){
print "$data{$key}\n";
}

执行以上程序,输出结果为:

1
2
3
google.com
runoob.com
taobao.com

示例测试

数据
Heilongjiang Haerbin
Jilin Changchun
Liaoning Shenyang
Hebei Shijiazhuang
Beijing Beijing
Tianjin Tianjin
Shanxi Taiyuan
Shandong Jinan
Anhui Hefei
Jiangsu Nanjing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/uer/bin/perl -w
use Data::Dumper;
%hash=();

open IN,"<$ARGV[0]";
while(<IN>) {
chomp; #标量
@line=split /\s+/,$_; #数组,s+是匹配任意空白符,至少一次
$hash{$line[0]}=$line[1]; #哈希
print "@line\n"
}
close IN;

# print Dumper (\%hash);

chomp ($province=<STDIN>);
if (exists $hash{$province}) {
print "The captial of $province is :\t";
print "$hash{$province}\n";
} else {
print "there is no data in the hash\n";
}

序列提取

哈希,在生物数据分析中最常用的一个方式,序列提取。根据固定的ID从另一个文件或者数据库中将数据提取出来,也就是根据一个小数据从一个大数据中提取数据。
处理方式:将小的数据集存储到一个哈希中,然后在遍历大的数据集查看哈希是否存在,如果 存在即输出,不存在不输出任何东西,循环继续进行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/perl -w
use strict;
use Data::Dumper;


if (scalar @ARGV==0) {
die "Usage: This program is used to get seqence by a list
perl $0 <name list> <fasta sequence>\n";
}

my %hash=(); #my是用来定义一个变量
open IN,"$ARGV[0]";
while (<IN>) {
chomp;
my @line=split /\s+/,$_;
$hash{$line[0]}=1;
}
close IN;

open FA,"<$ARGV[1]";
$/=">";<FA>;
while (<FA>) {
chomp;
my $temp=(split /\n/,$_,2)[0];
my $id=(split /\s+/,$_)[0];
if (exists $hash{$id}) {
print ">$_"; #因为前面开头少了一个>,所以这里加上
} else {
next;
}
}
close FA;

子程序

Perl 子程序也就是用户定义的函数。

Perl 子程序即执行一个特殊任务的一段分离的代码,它可以使减少重复代码且使程序易读。

Perl 子程序可以出现在程序的任何地方,语法格式如下:

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sub subroutine{
statements;
}

#调用子程序语法格式:

subroutine( 参数列表 );

#在 Perl 5.0 以下版本调用子程序方法如下:
&subroutine( 参数列表 );


sub hello {
print "Hello, world\n";
}

# 函数调用
hello();

执行以上程序,输出结果为:
Hello, world!

向子程序传递参数

Perl 子程序可以和其他编程一样接受多个参数,子程序参数使用特殊数组 @_ 标明。

因此子程序第一个参数为 $[0], 第二个参数为 $[1], 以此类推。

不论参数是标量型还是数组型的,用户把参数传给子程序时,perl默认按引用的方式调用它们。

定义求和函数

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/perl -w
use strict;

sub sum {
my $num1=5;
my $num2=8;
my $total=$num1+$num2;
return $total
}

my $total=&sum;
print "$total\n";

定义求平均值函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/perl

# 定义求平均值函数
sub Average{
# 获取所有传入的参数
$n = scalar(@_);
$sum = 0;

foreach $item (@_){
$sum += $item;
}
$average = $sum / $n;
print '传入的参数为 : ',"@_\n"; # 打印整个数组
print "第一个参数值为 : $_[0]\n"; # 打印第一个参数
print "传入参数的平均值为 : $average\n"; # 打印平均值
}

# 调用函数
Average(10, 20, 30);

执行以上程序,输出结果为:

传入的参数为 : 10 20 30 第一个参数值为 : 10 传入参数的平均值为 : 20

向子程序传递列表

由于 @_ 变量是一个数组,所以它可以向子程序中传递列表。

但如果我们需要传入标量和数组参数时,需要把列表放在最后一个参数上,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/perl

# 定义函数
sub PrintList{
my @list = @_;
print "列表为 : @list\n";
}
$a = 10;
@b = (1, 2, 3, 4);

# 列表参数
PrintList($a, @b);

以上程序将标量和数组合并了,输出结果为:

列表为 : 10 1 2 3 4

Perl 正则表达式

Perl的正则表达式的三种形式,分别是匹配,替换和转化:

匹配:m//(还可以简写为//,略去m)

替换:s///

转化:tr///

这三种形式一般都和 =~ 或 !~ 搭配使用, =~ 表示相匹配,!~ 表示不匹配。

匹配操作符

匹配操作符 m// 用于匹配一个字符串语句或者一个正则表达式,例如,要匹配 标量 $bar 中的 “run”,代码如下所示:

1
2
3
4
5
6
7
8
#!/usr/bin/perl -w
print "Do u like perl?\n";
my $choice=<STDIN>;
if ($choice=~ /y e s/ix) {
print "Yes,So you need to work hard\n";
} else {
print "No,So you need to work harder\n";
}

模式匹配修饰符

模式匹配有一些常用的修饰符,如下表所示:

修饰符 描述
i 忽略模式中的大小写
m 多行模式
o 仅赋值一次
s 单行模式,“.“匹配”\n”(默认不匹配)
x 忽略模式中的空白
g 全局匹配
cg 全局匹配失败后,允许再次查找匹配串

示例 - 提取以ATG开头-TAA结尾的序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/perl -w
use strict;

open IN,"<$ARGV[0]",or die "can not open the file\n$!";
while (<IN>) {
chomp;
if (/^ATG.*TAA$/i) { #如果‘!/^ATG.*TAA$/i’ 则表示匹配除此之外的序列。
print "$_\n";
} else {
next;
}
}
close IN;

单词锚定

search、searches ,searcher,searched,
searching、researching

  1. 只匹配search
    /\bsearch**\b**/

  2. 匹配search、searches、 searcher、searched、searching
    /\bsearch/

  3. 只匹配search、 research
    /search**\b**/

  4. 不匹配search
    /\Bsearch**\B**/

正则表达式变量

perl处理完后会给匹配到的值存在三个特殊变量名:

1
2
3
$`: 匹配部分的前一部分字符串
$&: 匹配的字符串
$': 还没有匹配的剩余字符串

示例

1
2
3
4
5
6
7
#!/usr/bin/perl

$string = "welcome to lxz9.com";
$string =~ m/lxz/;
print "匹配前的字符串: $`\n";
print "匹配的字符串: $&\n";
print "匹配后的字符串: $'\n";

执行以上程序输出结果为:

匹配前的字符串: welcome to
匹配的字符串: lxz
匹配后的字符串: 9.com

替换操作符

基本格式:s/PATTERN/REPLACEMENT/;

1
2
3
4
5
6
#!/usr/bin/perl

$string = "welcome to google site.";
$string =~ s/google/lxz/;

print "$string\n";

执行以上程序输出结果为:

welcome to lxz site.

替换操作修饰符

替换操作修饰符如下表所示:

修饰符 描述
i 如果在修饰符中加上"i",则正则将会取消大小写敏感性,即"a"和"A" 是一样的。
m 默认的正则开始"^“和结束”"只是对于正则字符串如果在修饰符中加上"m",那么开始和结束将会指字符串的每一行:每一行的开头就是"",结尾就是""只是对于正则字符串如果在修饰符中加上"m",那么开始和结束将会指字符串的每一行:每一行的开头就是"^",结尾就是""。
o 表达式只执行一次。
s 如果在修饰符中加入"s",那么默认的"."代表除了换行符以外的任何字符将会变成任意字符,也就是包括换行符!
x 如果加上该修饰符,表达式中的空白字符将会被忽略,除非它已经被转义。
g 替换所有匹配的字符串。
e 替换字符串作为表达式

转化操作符

以下是转化操作符相关的修饰符:

修饰符 描述
c 转化所有未指定字符
d 删除所有指定字符
s 把多个相同的输出字符缩成一个

以下实例将变量 $string 中的所有小写字母转化为大写字母:

1
2
3
4
5
6
#!/usr/bin/perl 

$string = 'welcome to lxz site.';
$string =~ tr/a-z/A-z/;

print "$string\n";

执行以上程序输出结果为:

WELCOME TO LXZ SITE.

以下实例使用 /s 将变量 $string 重复的字符删除:

实例

1
2
3
4
5
6
#!/usr/bin/perl

$string = 'lxzz';
$string =~ tr/a-z/a-z/s;

print "$string\n";

执行以上程序输出结果为:
lxz

更多实例:

string =~ tr/\d/ /c; # 把所有非数字字符替换为空格 string =~ tr/\t //d; # 删除tab和空格
$string =~ tr/0-9/ /cs # 把数字间的其它字符替换为一个空格。

更多正则表达式规则

表达式 描述
. 匹配除换行符以外的所有字符
x? 匹配 0 次或一次 x 字符串
x* 匹配 0 次或多次 x 字符串,但匹配可能的最少次数
x+ 匹配 1 次或多次 x 字符串,但匹配可能的最少次数
.* 匹配 0 次或多次的任何字符
.+ 匹配 1 次或多次的任何字符
{m} 匹配刚好是 m 个 的指定字符串
{m,n} 匹配在 m个 以上 n个 以下 的指定字符串
{m,} 匹配 m个 以上 的指定字符串
[] 匹配符合 [] 内的字符
[^] 匹配不符合 [] 内的字符
[0-9] 匹配所有数字字符
[a-z] 匹配所有小写字母字符
[^0-9] 匹配所有非数字字符
[^a-z] 匹配所有非小写字母字符
^ 匹配字符开头的字符
$ 匹配字符结尾的字符
\d 匹配一个数字的字符,和 [0-9] 语法一样
\d+ 匹配多个数字字符串,和 [0-9]+ 语法一样
\D 非数字,其他同 \d
\D+ 非数字,其他同 \d+
\w 英文字母或数字的字符串,和 [a-zA-Z0-9_] 语法一样
\w+ 和 [a-zA-Z0-9_]+ 语法一样
\W 非英文字母或数字的字符串,和 [^a-zA-Z0-9_] 语法一样
\W+ 和 [^a-zA-Z0-9_]+ 语法一样
\s 空格,和 [\n\t\r\f] 语法一样
\s+ 和 [\n\t\r\f]+ 一样
\S 非空格,和 [^\n\t\r\f] 语法一样
\S+ 和 [^\n\t\r\f]+ 语法一样
\b 匹配以英文字母,数字为边界的字符串
\B 匹配不以英文字母,数值为边界的字符串
a b
abc 匹配含有 abc 的字符串 (pattern) () 这个符号会记住所找寻到的字符串,是一个很实用的语法.第一个 () 内所找到的字符串变成 $1 这个变量或是 \1 变量,第二个 () 内所找到的字符串变成 $2 这个变量或是 \2 变量,以此类推下去.
/pattern/i i 这个参数表示忽略英文大小写,也就是在匹配字符串的时候,不考虑英文的大小写问题. \ 如果要在 pattern 模式中找寻一个特殊字符,如 “*”,则要在这个字符前加上 \ 符号,这样才会让特殊字符失效