Perl是一种高效处理文本文件的脚本语言,下面记录了一些常用的基因序列处理的perl函数或工具

数据类型

1、scalar

大小写转换工具:

1
2
3
4
uc $seq_of_BRAC2; #转大写
lc $seq_of_BRAC2; #转小写
$seq_of_BRAC2 =~ tr/atgc/ATGC/; #转大写
$seq_of_BRAC2 =~ tr/ATGC/atgc/; #转小写

利用tr工具统计4种碱基的个数

1
2
3
my $count = $seperate_dna =~ tr/atgc/atgc/; #统计$seperate_dna中小写atgc的数目
my $count = $seperate_dna =~ tr/ATGC/ATGC/; #统计$seperate_dna中大写ATGC的数目
my $count = $seperate_dna =~ tr/A/A/; #统计$seperate_dna中A的数目

取反向互补序列

1
2
my $reversed_zika_DNA = reverse($zika_DNA);
$reversed_zika_DNA =~ tr/ATCGatcg/TAGCTAGC/;

利用点符号连接字符串

1
2
3
4
my $M_codon = "AUG";
my $S_codon = "UCA";

my $RNA_seq = $M_codon.$S_codon;

统计字符串长度

1
2
my $zika_DNA = "AGTTGTTGATCTGTGTGAGT";
my $zika_DNA_lenth = length($zika_DNA);

替换掉序列中的空格及子片段

1
2
3
$seq_of_BRAC2 =~ s/\s//g;
$zika_DNA =~ s/atg/ATG/g;
$zika_DNA =~ s/[0123456789]//g;

格式化打印输出内容,分别打印3个最长长度为15,10,10的字符串

1
printf "%15s %10s %10s \n","Amino acid","1-letter","codon";

利用index函数的返回值判断一个字符串是否包含另一个字符串,返回-1表示不包含,返回其他数值表示$shorter_seq在$seq中的索引

1
2
3
4
5
6
7
my $index = index($seq,$shorter_seq);
if ($index eq -1){
print "the second sequence is not a substring of the first string";
}
else{
print "the second sequence is a substring of the first string";
}

取一个字符串在另一个字符串的索引值

1
2
3
my $first_index = index($up_dna,$motif); #取第一个索引值
my $second_index = index($up_dna,$motif,($first_index + length($motif))); #第三个参数为起始位置的索引
my $last_index = rindex($up_dna,$motif); #取最后一个索引值,如不包含,则返回-1

利用substr函数根据索引值在DNA序列里提取DNA片段

1
my $seperate_dna = substr($dna,$first_index + 4,$last_index - $first_index - 4); #3个参数分别表示DNA序列字符串、提取子片段的起始索引值、提取子片段的长度

2、array

数组内第一个元素的索引是0,$stop_codon[0]是@stop_codon的第一个元素

1
2
3
4
my @stop_codon = ("TAA","tAG");
print "Stop codon are @stop_codon\n";
my $first_stop_codon = $stop_codon[0];
$stop_codon[2] = "TGA"; #向数组添加元素

向数组内添加或去除元素

1
2
3
4
5
my @aa = ("GAA","GAG");
push (@aa,"GAU"); #在数组末尾添加元素
unshift (@aa,"GAC"); #添加第一个元素
pop @aa; #去除最后一个元素
shift (@aa); #去除第一个元素

利用sort对数组内元素进行排序

1
2
3
4
5
@input_line = sort(@input_line);

my @sorted_numbers = sort { $a <=> $b } @unsorted_numbers;
my @sorted_numbers1 = sort { $b <=> $a } @unsorted_numbers;
#sort { $a <=> $b } 升序;sort { $b <=> $a }降序

foreach依次对数组内元素进行操作

1
2
3
foreach my $i (@input_line){
print "$i\n";
}

利用scala函数统计数组内的元素个数

1
my $number_of_element = scalar @aa;

利用split函数分割字符串并存入数组

1
2
my $BRAC2_seq = "gggtgcgacgattcattgttttcggacaag";
my @nucleotides = split(//,$BRAC2_seq); #按照斜杠内部的符号切分每一个碱基并存入数组

利用join函数连接数组中的元素为一个字符串(与split相反)

1
my $BRAC2_seq = join('',@nucleotides); #单引号内为连接符,此处表示无连接符

3、hash

取哈希的键值分别存为数组

1
2
3
4
5
6
7
8
my %restriction_enzymes = ("EcoRI" => "GAATTC",
"AluI" => "AGCT",
"NotI" => "GCGGCCGC",
"TaqI" => "TCGA");
my @key_list = keys %restriction_enzymes;
print "@key_list\n";
my @value_list = values %restriction_enzymes;
print "@value_list\n";

删除哈希内部元素

1
delete $restriction_enzymes{"TaqI"};

循环与判断

perl的if-else结构:if(判断语句){执行语句;}else{执行语句;}

1
2
3
4
5
6
7
8
my $dna_segment = "ATGACATGA";
my $codon1 = substr($dna_segment,0,3);
if( $codon1 eq "ATG" ){
print "codon $codon1 is a start codon.\n";
}
else {
print "codon $codon1 is not a start codon.\n";
}

perl的if-elsif-else结构:if(判断语句){执行语句;}elsif(判断语句){执行语句;}else{执行语句;}

1
2
3
4
5
6
7
8
9
10
11
my $dna_segment = "ATGACATGACCAATAA";
my $codon = substr($dna_segment,-3,3);
if($codon eq "ATG"){
print "codon $codon is a start codon\n";
}
elsif(($codon eq "TAA") or ($codon eq "TAG") or ($codon eq "TGA")){
print "codon $codon is a stop codon\n";
}
else{
print "Codon $codon is neither a start nor a stop codon\n";
}

perl的while循环结构:while(判断语句){执行语句;}

1
2
3
4
while($index >= 0){
$reversed = $reversed.substr($zika_dna,$index,1);
$index = $index - 1;
} #此处利用序列的索引和while循环取反向序列

无限循环

1
2
3
while( ){
commands;
}

perl的foreach循环结构:foreach my $i (数组){执行语句}

1
2
3
4
my @bases = ("T","C","A","G");
foreach my $base (@bases){
print "$base";
}

perl的for循环结构:for(表达式1; 表达式2; 表达式3){执行语句;}

1
2
3
4
5
my $population = 425;
for (my $year = 0; $year <= 28; $year++){
print "at year $year, the population is $population\n";
$population = $population + $population * 0.0194;
}

文件操作

利用文件句柄FF打开文件,$!是一个魔术变量,对应于操作系统的数字错误代码,die函数会输出你指定的信息到专为这类信息准备的标准错误流中,并且让你的程序立刻终止并返回不为零的退出码。

读取文件,“<”表示将右侧文件的内容传递到左侧的文件句柄中;利用while循环逐行读取每一行的内容;利用close函数关闭文件句柄;

1
2
3
4
5
6
my $filename = "read_from_file.pl";
open (FF, "<", "$filename")or die "Cannot open $filename to write: $!";
while (my $line = <FF>){
print "$line";
}
close (FF);

写入文件,”>”表示将左侧句柄表示的内容传递给右侧文件

1
2
my $filename = "a.fas";
open (FF, ">", $filename)or die "cannot open $filename to write: $!";

open函数打开文件用法

模式 描述
< 只读方式打开,将文件指针指向文件头
> 写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之
>> 写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之
+< 读写方式打开,将文件指针指向文件头
+> 读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之
+>> 读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之

利用文件句柄FF写入内容至文件

1
2
print FF "ATG\n";
close (FF);

利用opendir函数打开文件夹

1
2
3
4
5
opendir ( DIR, $dirname ) || die "Error in opening dir $dirname\n";
while( ($filename = readdir(DIR))) {
print("$filename\n");
}
closedir(DIR);

判断是否存在文件

1
2
3
if (-e $filename){
print "Rosetta partial genome is written to $filename file successfully!\n";
}

其他文件测试操作 ( Other File Test Operators **)**,可以使用“和”(&&)或“或”(||)运算符一次测试两个或多个表达式。 其他一些文件测试运算符是:

-r checks if the file is readable #检查文件是否可读

-w checks if the file is writeable #检查文件是否可写

-x checks if the file is executable #检查文件是否可执行

-z checks if the file is empty #检查文件是否为空

-f checks if the file is a plain file #检查文件是否为纯文件

-d checks if the file is a directory #检查文件是否为目录

-l checks if the file is a symbolic link #检查文件是否为符号链接

正则匹配

1、判断字符串是否包含某个正则表达式

1
2
3
if ($seq =~ m/$motif/){
print "found the motif\n";
}

2、模式匹配成功后,会将匹配部分自动存储在变量$1中;

3、undef和defined函数,undef表示的像是数据库中的”null”。它表示空,啥也没有,是完全未定义的。这不等于字符串的空,不等于数值0,它是另一种类型。

1
2
3
4
$seq =~ m/($motif)/;
if (defined $1){
print "found the motif $1\n";
}

4、判断字符串是否匹配空行,^\s*$代表空行

1
2
3
if ($motif =~ m/^\s*$/){
last;
}

5、g表示全局匹配;

6、while ($seq =~ m/($motif)/g){}对所有地匹配进行循环操作;

7、pos()函数用于查找最后匹配的子字符串的偏移量或位置,如下面示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
my $seq = "AATGAAGGGCCGCTACGATAAGGAACTTCGTAATTTCAG";
print "seq = $seq\n";

my $motif = "[AT]{3,6}";
my $match_motif;
my $match_loc;
my $number_of_match = 0;

while ($seq =~ m/($motif)/g){
$match_motif = $1;
$match_loc = pos($seq) - length($match_motif);
$number_of_match = $number_of_match + 1;
print "matcg $number_of_match : $match_motif at $match_loc\n";
}

8、正则匹配将序列按照每10个碱基为一行打印出来

1
2
3
while ($seq =~ m/(.{1,$magic_number})/g){
print "$1\n";
}

正则表达式

1、正则字符及其含义

符号或字符 所表达意义
. 任何字符,除了换行符
\n 换行符
\t 制表符
\s 任何空白字符,包括空格、换行符、制表符
\S 任何非空字符
\d 任何数字
\D 任何非数字字符
\w 任何单个单词字符,包括字母和下划线
\W 任何单个非单词字符
* 匹配上一个字符0次或无数次
+ 匹配上一个字符1次或无数次
? 匹配上一个字符0次或1次 / 非贪婪匹配
{} 重复
{,} 重复,最小次数到最大次数
() 捕获 / 分组
\1 存储第一次捕获
\2 存储第二次捕获
\n 存储第n次捕获
^ 以某字符串开头
$ 以某字符串结尾
[] 一组字符中的任何一个字符
[^] 除了一组字符以外的任何字符
| 或者
\ 转义符
(?=…) Positive look-ahead. Matches if … matches next, but doesn’t consume any of the string
(?!…) Negative look-ahead. Matches if … doesn’t match next

2、正则表达式在DNA序列中的示例

正则表达式 示例 意义
AGA TAGATC 匹配AGA
^AGA AGATGC 匹配处于开头位置的AGA
TAA$ AAGTAA 匹配处于末尾位置的TAA
A.T AAACTG 匹配A和T以及两者之间任意一个字符(除换行符)
A.*T CATATCT 匹配A后面跟着任意数量的字符,然后是T(贪婪匹配)
A.*?T CATATCT 匹配A后面跟着任意数量的字符,然后是T(非贪婪匹配)
(A.*?T) CATATCT 捕获A后面跟着任意数量的字符,然后是T(非贪婪匹配)
A{5} TAAAAATC 匹配5个连续的A
TA{2,4}CG CTAAACGA 匹配T,跟着两个至4个范围的A,跟着CG
[AT]CG CCTTCGA 匹配ACG或TCG
[AA|CC|TT]CG ACCCGTA 匹配AA或CC或TT,然后跟着CG
A(CG){3}T GACGCGCGTA 匹配A,3个CG,跟着T
((.)(.)\3\2) GAATTAC 捕获4个连续字符,第1和第4个相同,第2和第3个相同
A\.T TCGA.TAA 匹配A.T,因为点被转义
AAA(?=TAG|TGA|TAA) TAAATGAT 匹配后面跟着TAG或TGA或TAA的AAA

Perl模块

子程序

参数传递

利用重定向符“>”将文件内容赋值给变量

perl inputs_as_an_array.pl < temp.txt

1
2
my @input_line = <STDIN>; #将temp.txt中的内容按照每行为一个元素传递给@input_line数组
#当不利于重定向时,可手动从键盘敲入@input_line数组的每个元素,回车键输入下一个元素,CTRL+D终止输入

利用@ARGV进行参数传递至脚本内部。当perl脚本运行时,从命令行上传递给它的参数存储在内建数组@ARGV中,@ARGV是perl默认用来接收参数的数组,可以有多个参数,$ARGV[0]是表示接收到的第一个参数,$ARGV[1]表示第二个。使用方法为:perl my.pl $ARGV[0] $ARGV[1]

1
2
3
4
5
if ($#ARGV < 0){
die "please provide a command line argument\n";
} #判断是否输入了命令行参数
my $seq = $ARGV[0]; #$ARGV[0]表示第一个参数
my $shorter_seq = $ARGV[1]; #$ARGV[1]表示第二个参数

利用标准输入

1
2
print "Enter a motif to search for: ";
$motif = <STDIN>;

其他函数

1、perl中的chomp函数将去掉行尾换行符;

2、eval函数用法:块中如果有一个语法错误或者运行时错误,或者一个”die” 语句被执行,”eval” 返回undef在标量上下文环境或者一个空的列表在列表环境。$@是存放错误信息的;

3、perl的qr函数用法:创建正则表达式。此函数将其STRING引用为正则表达式。STRING的插值方式与m/PATTERN/中的PATTERN相同;这个函数返回一个Perl值,它可以用来代替相应的/STRING/表达式。

1
2
3
4
5
chomp($motif);
eval{ qr/$motif/};
if ($@){
print "motif $motif is a an illegal regular expression!\n";
}

参考连接

Perl for Biologists

(22条消息) perl函数说明(eval)_易水寒江的博客-CSDN博客_eval perl

perl eval - czcb - 博客园 (cnblogs.com)

Perl qr实例讲解 - 码农教程 (manongjc.com)

Perl pos函数 - 基础教程 - 无涯教程网 (learnfk.com)

[(22条消息) Perl]Perl贪婪匹配、非贪婪匹配、占有优先匹配的區別和應用_元直数字电路验证的博客-CSDN博客_perl 贪婪匹配

perl–用die处理致命错误&用warn送出警告信息&自动检测致命错误 - 墨天轮 (modb.pro)

(22条消息) 如何判断Perl中是否存在文件_cumao2792的博客-CSDN博客

(22条消息) Perl文件目录操作_Hello Hunk的博客-CSDN博客_perl怎么进入文件夹