抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

最近在处理三代测序的下机数据,用到了一些挺好用的perl脚本,但是苦于没接触这种类型的编程语言,想根据情况改一些代码却看不懂实现方式= =

前面说学习perl可以只学怎么调用模块,马上啪啪打脸了,这货和python还是有点不一样的,还是抽空补补基础吧~现在做生信用的最多的就是R、python和perl,多掌握一门编程语言还是挺有必要的。记录一下自学的过程和笔记,自学视频来源是b站up主生信技能树-jimmy

示例

首先了解一下perl脚本的结构,以blast结果过滤的perl脚本为例,输入文件blast_m8.out是一个12列,分隔符为空格的文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/perl -w      # 选择解释器类型为perl,-w是运行错误时提供警告信息

open IN,"blast_m8.out"; # 打开文件,m8格式输出的blastout文件。每次只读一行
while (<IN>) { # 大括号为程序块,每个程序块是一个独立的部分,执行相对独立的功能
chomp; # 去掉读进来数据结尾的换行符\n(没有换行符则不起作用)
my @line=split /\s+/,$_; # 以空白分割(\s是匹配任何空白符,+表示匹配任意多个),存入数组中
if ($line[2] >=50 && $line[3] >=100) {
print "$_\n"; # 将第三列identity值大于50,第四列序列长度大于100的blast结果输出
} else {
next; # 否则进入下一个循环
}
}
close IN;
# 这个脚本第四行的my也要注意下,一般是需要申明use strict;也就是使用严谨的方式,在这种方式下,任何变量都必须先定义,不使用my的话定义第一次出现的$和@运行会报错。初学可以不使用use strict。
# $_这个变量是使用非常多的,如果没有定义变量名称,则默认使用$_

OK,格式与python不一样,以分号作为每一行结尾,基础语法类似但不完全一样,先从基础学起。

1 标量数据

标量数据特点

  • perl中最基本的数据类型
  • 可以是数字、字母
  • 无需定义类型(所有perl语言的数据都是双精度浮点型,不需要对数据类型进行定义,代价是消耗内存)
  • “单数为标量”

字符串运算

  • 字符串就是一连串字符组合,可以是字母数字标点等
  • 对DNA序列处理本质上就是处理字符串
  • 字符串可以为空
  • 需要“引号”,尽量使用双引号
  • 字符串连接“.”或者“x” 如 “hello” . “world”

标量变量

标量变量用来动态存储标量值,以美元符号$表示(定义数组用@符号),和linux一样不能以数字开头

1
2
3
4
5
6
# 一个=表示赋值,两个==表示判断,这里和python是一样的
$gene_num=3
$gene_num=$gene_num+4
$gene_num+=4 # 双目运算符,运算所需变量为两个运算符,这个简写是非常常用的
$dna="ATCGGGTATCG"
$dna.="ATCGGGTCG" # 双目运算符同样可以用于字符串操作,得到标量变量为连接的字符串

2 数组和列表

数组构建

列表(list)指标量的有序集合,数组(array)则是存储列表的变量

1
2
3
4
5
6
7
@array=(1,"hello",undef,$dna,5);      # 左边为数组,右边为列表,构建列表中间用逗号隔开
$array[0]=1;
$array[1]="hello" # 注意下标数字从0开始,0表示第一个元素
数组的最后一个元素角标$#array,因此数组元素个数=$#array+1

@number=(1..100) # 范围操作符(..)每次加一
@string=qw (fred barney betty wilma dino) # qw操作符可以省略逗号

split和join函数

  • split将字符串根据固定的分隔符进行切割,切割后得到一个数组
  • join与split相反,将数组连接成一个标量
1
2
3
4
5
6
7
8
#!/bin/perl

$scalar="a:bcd:123:de";
@array=split /:/,$scalar; # 以冒号作为分隔符分割
print "@array\n"

$new_scalar=join "\t",@array; # 以制表符作为分割符,好处是excel里打开每个元素在不同单元格
print "$new_scalar\n"

pop和push函数

1
2
3
4
5
#!/bin/perl
@number=(1,2,3,4,5);
$value=pop @number; # pop提取数组的最后一个元素
push @number,6; # push添加一个元素到数组的末尾
print "$value\n@number\n";

shift和unshift函数

1
2
3
4
5
#!/bin/perl
@number=(1,2,3,4,5);
$value=shift @number; # shift提取数组第一个元素
unshift @number,10; # unshift添加一个元素到数组的开头
print "$value\n@number\n";

一般来说pop和shift用的比较多,一个提取数组末尾元素,一个提取数组开头元素。

因为我们用perl处理的往往是矩阵文件,第一行是ID信息,我们往往是读入一行数据,去掉换行符,存储为标量,分割数组。这个时候就要用shift函数,将ID提取出来,这样呢后面都是同一种类型的数据,方便我们操作,也就是底下这个框架:

1
2
3
4
5
6
7
#!/bin/perl
while (<IN>) {
chomp;
my @line=split /\s+/,$_;
my @id=shift @line;
print "$id\n"
}

sort和reverse函数

1
2
3
4
#!/bin/perl
@number=(1..10);
@number_sort=sort @number; # sort函数使数组按照ASCII码大小排序
print "@number_sort\n";

可以看到10在1的后面,因为sort函数是以ASCII码大小进行排序的。

1
2
3
4
#!/bin/perl
$dna="ATCGCGTAGCATCGATGCTGATCATGC";
$dna_reverse=reverse $dna; # reverse函数可以使数组或者字符串反转
print "$dna_reverse\n";

reverse函数在做DNA反向互补配对的时候能用到。

foreach遍历数组

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/perl
@number=(1..10);
foreach $num (@number) { # 遍历数组中的值依迭代
print "$num\n";
}

# 也可以省略一部分内容
#!/bin/perl
@number=(1..10);
foreach (@number) { # 省略了$num,存储到默认的$_中
print;
}

欢迎小伙伴们留言评论~