一、常用正则表达式
1、元字符
-
\
反斜线:转义符; -
.
点号:代替任何一个单字符,除了换行符以外; -
*
星号:表示前面的字符重复0到多次;
若前面的字符加上括号,就表示括号内字符串为整体进行模式匹配,下同。 -
+
加号:表示前面的字符重复1到多次; -
?
问号:表示前面的字符重复0或1次; -
{1,8}
大括号:表示手动设定匹配重复的范围; -
.*
点星组合:表示任意长度字符串,常用;
2、字符集
-
(b|c|d|e|h|z)at
、[bcdehz]at
、[b-fhz]at
三者表达意义相同,择一匹配。 -
[a-z]
表示小写字母集;[A-Z]
表示大写字母集。 -
[0-9]
表示任一数字,等价于\d
;\d+
表示任意长度数字(常用),类似的是\s+
表示任意长度空白(也很常用),比如my @line=split /\s+/,$_;
-
\w
表示任一数字,字母以及下划线;即等价于[a-zA-Z0-9_]
-
^
与$
分别表示行首、行尾匹配;举一例便明白了^ATG.*TAA$
表示匹配以ATG开头、以TAA结尾的序列。
注意:如果脱字符^
用于[ ]
中,就表示取反;比如[^0-9]
表示匹配一个非数字字符,等价于[^\d]
、\D
这里顺带复习下vim的操作:d^表示删除光标至行开头的地方;d$表示删除光标至行结尾的地方
二、使用正则表达式
1、配合if,判断是否存在特定类型字符
即用到正则表达的匹配 ,格式为m/<1>/<2>
-
m
表示匹配格式,若匹配到则为真,否则为假;可以省略。 -
/ /
为界定符,也可以为其它,比如! !
等; -
<1>
即为想要匹配的模式,通常会用到第一点的知识; -
<2>
为修饰符,即为对匹配过程的功能修饰,见下面的例子;可省略。
1.1、最简单的例子
#!/usr/bin/perl -w
use strict;
$_="hello,world!"
if (/hello/) { #在变量值中匹配是否有“hello”,有则为真;否则为假
print "it is matched\n"
} else {
print "it is not matched\n"
}
注意如果
if ( /<1>/)
条件括号内不加变量名,即表示与$_
标量匹配;
if ( $sample=~ /<1>/)
即为与某特定变量进行匹配的格式。
1.2、匹配输出特定序列
#!/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结尾的序列文件
#if (!/^ATG.*TAA$/i) {
#表示匹配不是以ATG开头,TAA结尾的序列文件
print "$_\n";
} else {
next;
}
}
close IN;
perl 002.pl seq.txt
1.3、匹配修饰符
#!/usr/bin/perl -w
print "Do u like perl?\n";
my $choice=<STDIN>; #从标准输入获取信息
if ($choice=~ /y e s/ix) {
# i修饰符 表示忽略大小写
# x修饰符 表示忽略空格
print "Yes,So you need to work hard\n";
} else {
print "No,So you need to work harder\n";
}
2、捕获文本中特定类型的字符
-
( )
小括号加在正则表达式中,表示捕获括号内的特定类型字符赋值给变量。 - 一般第一对括号赋值给
$1
变量;第二对括号赋值给$2
变量....
注意由于上文提到小括号还有整体分组的功能;为了避免此功能的矛盾,设置
(?: )
表示仅有整体分组功能,不捕获值。
- 一个复杂的例子:取出"Score = 161 bits (407), Expect = 1e-43, Method: Compositional matrix adjust."文本字符串中的Score值与Expect值。
#!/usr/bin/perl -w
use strict;
my $line1="Score = 161 bits (407), Expect = 1e-43, Method: Compositional matrix adjust.";
my @result= ($line1=~ m/Score\s*=\s*([\d\.\,]+)\s*bits\s*\(\d+\)\,\s*Expect\s*=\s*(\S+),/);
print "@result\n";
此处的正则表达式比较长,
(\S+)
存疑,我替换成(\w+)
就输出为空白了,奇怪。慢慢理解下~
3、正则替换
模式为 s/ <1> / <2> /
-
s
表示替换,不可省略; -
<1>
为匹配内容,即被替换的文本; -
<2>
为替换的文本;若为空,就表示删除;
#!/usr/bin/perl -w
use strict;
my $line="hello,world!";
$line=~ s/world/China/; #替换单词
$line=~ s/^/Nihao,/; #在行首添加内容
$line=~ s/$/hello!/; #在行尾添加
$line=~ s/hello/ /g; #删除所有的hello
# g修饰符表示全局替换,否则只会删除第一个;
my $num+=($line=~ s/hello!/ /g);
# 赋值给变量的值是成功替换的次数,在统计特定文本个数是有用。
print "$line\n";
print "$num\n";
补充1:一一对应替换
- 示例:获得序列的互补序列,即A-T、T-A、C-G、G-C四种替换(N碱基不变);
- 不能使用
s
模式;可以使用tr
模式
#!/usr/bin/perl -w
use strict;
my $seq="TTATCCCTAAAATNGTNNNAGTATAAACATAAGA";
# my $r_seq=reverse $seq;
# 如果想要获得反向互补序列,可以先reverse一下
my $r_seq=$seq;
$r_seq=~ tr/ATCG/TAGC/;
print "$seq\n"; #原始序列
print "$r_seq\n"; # 互补序列
补充2:大小写替换
my $seq="TTATCCCTAAAATNGTNNNAG";
$seq=~ s/(\w+)/\U$1/g; #全部变成大写
$seq=~ s/(\w+)/\L$1/g; #全部变成小写
$seq=~ s/(\w+)/\u$1/g; #首字母大写
巧妙利用了
( )
捕获与$1
变量的关系。
补充3:贪婪匹配(替换)
-
+*?
等都尽可能的多匹配长字符串,即贪婪匹配
my $seq="ATGTCCC1TAAAATNGTNN2TAA";
if ($seq=~ /^ATG(.+)TAA/i) {
print "$1\n";
}
- 此例中,通过再加
?
,取消贪婪、匹配最短序列。
my $seq="ATGTCCC1TAAAATNGTNN2TAA";
if ($seq=~ /^ATG(.+?)TAA/i) {
print "$1\n";
}