BGI-College生信入门——7、Perl小骆驼学习笔记(二)

「子程序」

用户自定义的函数,调用子程序也叫做呼叫(calling)子程序

函数名由字母、数字和下划线组成,但是不能以数字开头

sub subroutine{

statements;

}

#举个例子,定义一个寻找最大值的子程序

sub getMaximun{

my @array=sort {$a<=>$b} @_;

my$max=$array[-1];

return$max;

}

#调用子程序

my @a=qw/11 22 33 44 55/;

my$max=getMaximun(@a);

#子程序中的sort {$a <=> $b} @_是对数组元素从小到大排序,因此数组中最后一个元素值($array[-1])即最大值

1.子程序参数使用特殊数组(@_),因而第一个参数为($_[0]),以此类推

2.可以使用return语句返回数值

3.私有变量用操作符my定义

4.可用local给全局变量赋值,但不影响主程序中该变量的值,只在该子程序和被调用的子程序中发挥作用

5.最后一次运算的结果是子程序的返回值

「输入与输出」

「文件句柄」

简单而言,文件句柄就是Perl进程与外部的I/O联系的名称

通常采用open函数打开文件

#以只读方式打开文件file.txt

open(F,"

#以写入方式打开file.txt

open(F,">file.txt");

#以追加写入方式打开file.txt

open(F,">>file.txt");

「文件句柄的命名不要与特殊的文件句柄重名」

6个特殊的文件句柄

STDIN

STDOUT

STDERR

DATA

ARGV

ARGVOUT


die处理致命错误:die "Cannot creat logfile:$!";

$!表示可读的系统错误信息,例如"permission denied"或"file not found"之类

die结尾加上换行符"\n"则表示不显示行号和文件名:die "Not enough arguments\n";


warn发送警告信息,但不中断程序运行,die会终止程序运行

自动检测致命错误:use autodie;

say进行输出,与print相似,但打印每行内容时会自动加上换行符


标量变量中的文件句柄

my$rock_fh;

open$rock_fh,'<','rock.txt'or die"Could not open rocks.txt: $!";

#等效于

open my$rock_fh,'<','rock.txt'or die"Could not open rocks.txt: $!";

「正则表达式」

「简单模式」

若对象是$_的内容,只需要用一对斜线(/string/),配合if/while的条件表达式

「Unicode属性」

匹配某项属性

if(/\p{Space}/){

print"The string has some whitespace.\n";

}

#若是匹配数字,可使用\p{Digit}

if(/\p{Digit}/){

print"The string has some digital number.\n";

}

#若想匹配不包含特定属性的字符串,则使用\P

if(/\P{Digit}/){

print"The string has no digital number.\n";

}

「元字符」

点号(.)只能任意匹配一个字符(换行符除外)

匹配句号需要加反斜线(\)

反斜线使元字符失去特殊作用

(^)匹配行首,字符集里表示求补集

($)匹配行尾

(.)除新行外的任一字符,在s/中匹配包括换行符在内的任一字符

(|)匹配左边或右边,择一匹配


'()'模式分组字符,反向引用括号中匹配的文字,即捕获组

反向引用写法(\1、\2,数字表示对应顺序的捕获组)

消除连续数字产生的歧义

\g{N},其中N表示组号,若N为负数,则表示从\g{N}位置向前数第N个括号

「如何理解模式分组和反向引用?」

通过元字符我们知道如何去匹配单个字符,但若要匹配字符串,特别字符串中有2处及以上未知子串时,就需要通过分组捕获,再通过反向引用访问捕获到的字符串

例如,我爬虫获取了梦华录电视剧剧集和对应的人物信息,想要整理出每一集中出现的人物

"Menghualu01_Zhaopaner_Guqianfan"=~ /Menghualu([0-9]*)_([a-zA-Z]*)_([a-zA-Z]*)/;

print"梦华录第$1集人物:$2$3\n";

#运行结果:

梦华录第01集人物:Zhaopaner Guqianfan

#这里使用圆括号对匹配的子串作分组,从左到右分别是1、2和3   

#因为Perl中会将匹配的内容存入特殊变量$N中,我们可以通过$1、$2和$3访问捕获到的剧集和人物信息   

#其中,$1表示剧集数,$2和$3表示对应剧集中出现的人物名字

「量词」

星号(*)匹配零次或多次

加号(+)匹配一次或多次

问号(?)匹配零次或一次

{n}匹配n次

{n,}至少匹配n次

{n,m}匹配n-m次,如a{1-10}表示匹配重复1到100次的字母a

「字符集」

'[]'表示一类字符集中的任意一个,匹配单个字符;'-'表示范围

如[0-9]表示匹配数字0-9,[^0-9]表示匹配除0-9数字外的字符

字符集简写:

\d => [0-9],\D => [^0-9]

\w => [a-zA-Z0-9_],\W => [^a-zA-Z0-9_]

\s => [\f\t\n\r],\S => [^\f\t\n\r]

\h => [\t]

\v => [\f\n\r]

\R =>任意类型的换行符

「正则匹配」

/i:表示不区分大小写,/chr/i

/s:点号(.)在其中表示匹配任意字符,包括换行符

/x:忽略空白符,更易阅读

$a="hello\ntomorrow is another world";

if($a=~ /hello.*world/s){

print"it's ok.\n";

}

学完一轮基础的Perl,下面简单分析一个根据id信息提取相应序列的perl脚本(https://blog.csdn.net/weixin_40099163/article/details/88723572)

学习编程最快的方式就是看懂别人写的代码

#!/usr/bin/perl -w

1 unless(@ARGV==3){

2    die"Usage: perl$0   error:$!\n";

3 }

4 my($lst,$input,$output)=@ARGV;

5 open LST,$lst;

6 open INPUT,$input;

7 open OUTPUT,">$output";

8while(){

9     chomp;

10if($_=~ /^>..*/){

11$keys=$_;

12     }

13else{

14$hash{$keys} .=$_;

15     }

16 }

17while(){

18     chomp;

19if($_=~ /^>..*/){

20$ID=$_;

21printOUTPUT$ID."\n".$hash{$ID}."\n";

22     }

23else{

24$ID=">".$_;

25printOUTPUT$ID."\n".$hash{$ID}."\n";

26     }

27 }

第1-3行,@ARGV是收集命令行参数的数组,这里规定用户必须提供3个参数,即ID列表文件(ID_lst)、输入序列文件(input_fasta)和输出序列文件(output),其中第2行的表示该脚本的名称

第4行,将用户输入的3个文件名依次赋值给数组@ARGV

第5行,通过文件句柄LST打开ID列表文件

第6行,通过文件句柄INPUT打开输入序列文件

第7行,通过文件句柄OUTPUT以写入方式打开输出序列文件

第8行,遍历输入序列文件

第9行,去除行尾换行符

第10行,判断该行是否以大于号(>)开头,即判断该行是否为序列ID

第11行,将匹配成功行的内容赋值给keys,keys即序列ID

第14行,将匹配失败行的内容赋值给哈希%hash{keys},即将ID存为哈希的键,ID对应的序列存为哈希键对应的值,其中出现的双目赋值符(.=)考虑了序列为多行格式的情况

第17行,遍历输入的ID列表文件

第18行,同第9行

第19行,判断用户输入的ID名是否带大于号

第20行,把匹配成功的行赋值给$ID

第21行,通过哈希中键值对一一对应的关系,打印输出序列文件 第24行,若ID不以大于号开头,则在开头加上大于号再输出到OUTPUT

你可能感兴趣的:(BGI-College生信入门——7、Perl小骆驼学习笔记(二))