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");
#以写入方式打开file.txt
open(F, ">file.txt");
#以追加写入方式打开file.txt
open(F, ">>file.txt");

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

6个特殊的文件句柄

  1. STDIN
  2. STDOUT
  3. STDERR
  4. DATA
  5. ARGV
  6. ARGVOUT

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

  1. $!表示可读的系统错误信息,例如"permission denied"或"file not found"之类
  2. 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. 反向引用写法(\1、\2,数字表示对应顺序的捕获组)
  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数字外的字符
字符集简写:

  1. \d => [0-9],\D => [^0-9]
  2. \w => [a-zA-Z0-9_],\W => [^a-zA-Z0-9_]
  3. \s => [\f\t\n\r],\S => [^\f\t\n\r]
  4. \h => [\t]
  5. \v => [\f\n\r]
  6. \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 <ID_lst> <input_fasta> <output> error:$!\n";
  3 }
  4 my($lst, $input, $output)=@ARGV;
  5 open LST, $lst;
  6 open INPUT, $input;
  7 open OUTPUT, ">$output";
  8 while(<INPUT>){
  9     chomp;
 10     if($_ =~ /^>..*/){
 11         $keys = $_;
 12     }
 13     else{
 14         $hash{$keys} .= $_;
 15     }
 16 }
 17 while(<LST>){
 18     chomp;
 19     if($_ =~ /^>..*/){
 20         $ID = $_;
 21         print OUTPUT $ID."\n".$hash{$ID}."\n";
 22     }
 23     else{
 24         $ID = ">".$_;
 25         print OUTPUT $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
 

posted @ 2022-07-19 16:15  华大基因学院  阅读(104)  评论(0编辑  收藏  举报