搜索
查看: 731|回复: 6

[Perl] Perl中正则表达式用法总结

[复制链接]

8

主题

49

帖子

224

积分

版主

Rank: 7Rank: 7Rank: 7

积分
224
发表于 2016-9-16 19:18:20 | 显示全部楼层 |阅读模式
1)、正则表达式的三种形式:
首先我们应该知道 Perl 程序中,正则表达式有三种存在形式,他们分别是:
1、匹配:m/<regexp>;/ (还可以简写为 /<regexp>;/ ,略去 m)
2、替换:s/<pattern>;/<replacement>;/
3、转化:tr/<pattern>;/<replacemnt>;/
这三种形式一般都和 =~ 或 !~ 搭配使用(其中 "=~" 表示相匹配,在整条语句中读作 does,"!~" 表示不匹配,在整条语句中读作 doesn't),并在左侧有待处理的标量变量。如果没有该变量和 =~ !~ 操作符,则默认为处理 $_ 变量中的内容。举例如下:
[Perl] 纯文本查看 复制代码
$str = "Hello World";
$str =~ m/Hello/; # 表示如果在 $str 中发现 "Hello" 字符串,则返回 "1" 否则返回 "0"。
$str =~ s/Hello/Hi/; # 表示将变量 $str 中的 "Hello" 字符串替换为 "Hi",如果发生此替换则返回 "1",否则返回 "0"。
$str !~ tr/A-Z/a-z/; # 表示将变量 $str 中的所有大写字母转化为小写字母,如果转化发生了则返回 "0",否则返回 "1"。
foreach (@temp) { s/a/b; } # 表示此处每次循环从数组 @temp 中取出一个元素存放在 $_ 变量中,并对 $_ 进行 b 替换 a 的处理。
while (<INFILE>;) { print if (m/false/); } # 表示将打印文件 INFILE 中所有包含字符串 false 的行。


Perl 的正则表达式中如果出现 () ,则发生匹配或替换后 () 内的模式被 Perl 解释器自动依次赋给系统 $1, $2 ...... 请看下面的例子:
[Perl] 纯文本查看 复制代码
$string = "Hello World";
$string =~ s/(Hello)/<$1>;/; # 此时 $1 = "Hello",并且该替换的结果是将 $string 变为 "<Hello>; World"
$string = "Hello World";
$string =~ s/(He)(.*)(World)/<$3>;$2<$1>;/; # 这里 $1 = "He",$2 = " llo ",$3 = "World",并且替换后 $string 变为 "<World>; llo <He>;"


替换操作 s/<pattern>;/<replacement>;/ 还可以在末尾加上 e 或 g 参数,他们的含义分别为:
s/<pattern>;/<replacement>;/g 表示把待处理字符串中所有符合 <pattern>; 的全部替换为 <replacement>; 字符串,而不是只替换第一个出现的模式。
s/<pattern>;/<replacement>;/e 表示将把 <replacemnet>; 部分当作一个运算符,这个参数用的不多。
[Perl] 纯文本查看 复制代码
$string = "i:am:luna";
$string =~ s/:/*/; #此时 $string="i*am:luna";
$string = "i:am:luna";
$string =~ s/:/*/g; #此时 $string="i*am*luna"; 
$string =~ tr/*/ /; #此时 $string="i am luna"; 
$string = "www11biotrainee33com";
$string =~ s/(\d+)/$1*2/e; # (/d+)代表 $string 中的连续数字字符,将这些数字字符执行 *2 的操作,因此最后 $string 变成了 "www22biotrainee66com"。


2)、正则表达式中的常用模式
/pattern/
"." 用来匹配任意一个字符(除了"\n"换行符)的通配符,用的最多的,但是经常出问题的也是这个
"*" 用来匹配前面条目出现零次以上(包含零次)
"+" 用来匹配前面条目出现一次以上(至少一次)
"?" 用来匹配前面条目出现一次或者不出现
"()" 用来对字符串分条目,\1 或 \2 可以反向引用括号里的字符串,相应的数字表示对应顺序的捕获条目,若要调用()中的捕获条目,可用$1,$2依次表示,也可以用$+{LABEL}标签形式捕获
[Perl] 纯文本查看 复制代码
/(.)\1/        表示匹配2个连续的字符,比如'aa'
/(\S)\1/       匹配连续出现2次的非空字符
/(.)(.)\2\1/   可以匹配'abba'
/(.)\g{1}11/   可以用\g{N},N为数字来表示反向引用,消除歧义
/(?:bronto)?saurus (steak|burger)/   圆括号中使用?:表示不对该圆括号的内容进行捕获
/(?<name1>\w+) (?:and|or) (?<name2>\w+)/  用?<LABEL>表示对捕获组的引用

对于自动捕获变量,可以用$&表示匹配到的字符串,$`表示字符串匹配前的字段,$'表示字符串匹配后的字段,也可以分别用${^MATCH},${^PREMATCH},${^POSTMATCH}表示
转义元字符,若要匹配"."号本身,需要使用"\"转义,"\.",对"\"本身匹配,则为"\\","*"则为"\*",这样才会让特殊字符失效


{m} 匹配刚好是 m 个 的指定字符串                                   # /lu{2}na/ 找到 l 后面跟着 2个 u,再跟着 na 的字符串
{m,n} 匹配在 m个 以上 n个 以下 的指定字符串                 # /lu{2,4}na/ 找到 l 后面跟着2~4个 u,再跟着 na 的字符串
{m,} 匹配 m个 以上 的指定字符串                                     # /lu{2,}na/ 找到 l 后面跟着 2个以上 u,再跟着 na 的字符串
[] 匹配符合 [] 内的字符                                                      # /[luna]/ 找到符合 luna 中任意一个的字符串
[^] 匹配不符合 [] 内的字符                                                # /[^luna]/ 找到没有 luna 中任意一个的字符串
[0-9] 匹配所有数字字符
[a-z] 匹配所有小写字母字符
[^0-9] 匹配所有非数字字符
[^a-z] 匹配所有非小写字母字符
[a-zA-Z0-9] 匹配所有的英文字母或数字的字符串,另有一个是 \w
[^a-zA-Z0-9] 匹配非英文字母或数字的字符串,另有一个是 \W
\w+ 和 [a-zA-Z0-9]+ 语法一样
\W+ 和 [^a-zA-Z0-9]+ 语法一样

^ 匹配字符开头的字符 ,相反  $ 匹配字符结尾的字符        #/^lu.*na$/表示以 lu 开头, na 结尾的字符串
\d 匹配一个数字的字符,前提是在ASCII字符集中,相反,"\D"表示否定含义,表示非数字,\d 和 [0-9] 语法一样
\d+ 匹配多个数字字符串,相反,"\D+"表示否定含义,表示多个非数字,\d+ 和 [0-9]+ 语法一样
\s 空格,和 [\n\t\r\f] 语法一样
\s+ 和 [\n\t\r\f]+ 一样
\S 非空格,和 [^\n\t\r\f] 语法一样
\S+ 和 [^\n\t\r\f]+ 语法一样
\b 匹配以英文字母,数字为边界的字符串
\B 匹配不以英文字母,数值为边界的字符串
a|b|c 匹配符合a字符 或是b字符 或是c字符 的字符串,和[abc]是一样的
abc 匹配含有 abc 的字符串 ,(pattern) () 这个符号会记住所找寻到的字符串,是一个很实用的语法。第一个 () 内所找到的字符串变成 $1 这个变量或是 \1 变量,第二个 () 内所找到的字符串变成 $2 这个变量或是 \2 变量,以此类推下去。  
/pattern/i i 这个参数表示忽略英文大小写,也就是在匹配字符串的时候,不考虑英文的大小写问题。






上一篇:Top N Reasons To Do A Ph.D. or Post-Doc in Bioinformatics/Computational Biology
下一篇:shell自动下载常见物种的基因组文件
我的微博:dulunar
回复

使用道具 举报

8

主题

49

帖子

224

积分

版主

Rank: 7Rank: 7Rank: 7

积分
224
 楼主| 发表于 2016-9-16 19:22:06 | 显示全部楼层
本帖最后由 dulunar 于 2016-9-16 19:44 编辑

[Perl] 纯文本查看 复制代码
"//s",s默认转换模式中的点号为字符集[\d\D],因此点号可以匹配换行符
/Barney.*Fred/s     若Barney和Fred之间有换行符则不影响匹配
"//x",x允许在模式中插入任意空白符,增加可读性
/ -? [0-9]+ \.? [0-9]* /x 
"//a", 表示以ASCII字符集的模式匹配
/\w+/a              代表[a-zA-Z0-9_]字符集
"//u",表示以unicode字符集的模式匹配
/\w+/u              代表Unicode中定义为单词的字符
"//l",表示以本地化所设定的字符集的模式匹配
/\w+/l              代表locale本地化设定的字符集
"\A" 锚位匹配字符串的绝对开头,
/\Astring/ 
"\z" 锚位匹配字符串的绝对末尾,"\Z" 允许后面出现换行符
/string\z/ 
"//m"可以对多行字符串进行匹配,和"$","^"结合使用
/fred$/m        匹配多行字符串中fred结尾的 
/^barney/m      匹配多行字符串中barney开头的
"\b" 单词锚位,
/\bFred\b/    匹配一个独立的单词Fred,前后不能结合其他字符
"=~" 绑定操作符,指定字符串和模式进行匹配,若不用绑定操作符,默认对$_变量进行匹配
string =~ /expr/ 
我的微博:dulunar
回复 支持 反对

使用道具 举报

8

主题

49

帖子

224

积分

版主

Rank: 7Rank: 7Rank: 7

积分
224
 楼主| 发表于 2016-9-16 19:28:01 | 显示全部楼层
本帖最后由 dulunar 于 2016-9-16 19:29 编辑

替换的用法举例
[Perl] 纯文本查看 复制代码
$_ = "green scaly dinosaur"; 
s/(\w+) (\w+)/$2, $1/;       将2个字符串互换位置,换后为"scaly, green dinosaur"
s/^/huge,/;                  在开头插入huge,变为"huge,scaly,green dinosaur"
s/,.*een//;                  将第一个逗号到green的所有字符都删除,变为"huge dinosaur"
s/\w+$/($`!)$&/;             替换后变为"huge (huge !)dinosaur"
s/\s+(!\W+)/$1 /;            替换后变为"huge (huge!) dinosaur"
s/huge/gigantic/;            替换后变为"gigantic (huge!) dinosaur"


s///g,/g为全局替换

大小写替换
在替换运算中,常常需要把替换的单词改写成全部大写或小写。
\U:全大写
\L:全小写
\l: 只影响后面紧跟的第一个字符,小写
\u:首字母大写
[Perl] 纯文本查看 复制代码
$_ = "I saw Barney with Fred .";
s/(fred|barney)/\U$1/gi;         =>        "I saw BARNEY with FRED ."
s/(fred|barney)/\L$1/gi;         =>        "I saw barney with fred ."
s/(\w+) with (\w+)/\U$2\E with $1/i; =>        "I saw FRED with barney ."
s/(fred|barney)/\u$1/gi;         =>        "I saw FRED with Barney ."
s/(fred|barney)/\u\L$1/ig;        =>       "I saw Fred with Barney ."


默认情况下,\E,\L会影响到后面全部的替换字符串,你可以用\E关闭大小写转换功能。





我的微博:dulunar
回复 支持 反对

使用道具 举报

8

主题

49

帖子

224

积分

版主

Rank: 7Rank: 7Rank: 7

积分
224
 楼主| 发表于 2016-9-16 19:42:18 | 显示全部楼层
本帖最后由 dulunar 于 2016-9-16 19:43 编辑

split操作符,可以将字段中的以某个特定分隔符分隔开的字符串提取出来并存入列表变量
对于使用制表符(\t)、冒号(、空白( )或任意符号(; / , 等等)分隔不同字段的字符串来说
用split提取字段相当方便。只要将分隔符写成模式(通常是很简单的正则表达式):
[Perl] 纯文本查看 复制代码
my @temp = split /\./,"www.biotrainee.com"; =>("www","biotrainee","com");
my @temp = split /:/,"abc:def:g:h"; =>("abc","def","g","h");
my @temp = split /:/,"abc:def::g:h"; =>("abc","def","","g","h");
my @temp = split /:/,":::a:b:c:::"; =>("","","","a","b","c");

如果两个分隔符连在一起,就会产生空字段。并且split会保留开头的空字段,而会舍弃结尾处的空字段. 利用split的/\s+/模式根据空白符分隔字段也是比较常见的做法:
[Perl] 纯文本查看 复制代码
my @temp = split /\s+/,"my      name\tis\tluna   ";=>("my","name","is","luna");
my @fields = split;   <=> split /\s+/,$_;


join函数
与split刚好相反,join函数将片段用指定的连接符合成一个字符串,将指定的分隔符插入到不同的字符串中。

[Perl] 纯文本查看 复制代码
my $website = join ".","www","biotrainee","com";      得到的变量$website是 [url]www.biotrainee.com[/url]
my @temp = split /\./,$website;
my $site = join ".",@temp;


join的列表至少有两个元素,否则不起作用。join经常与split联合使用。


我的微博:dulunar
回复 支持 反对

使用道具 举报

0

主题

1

帖子

16

积分

新手上路

Rank: 1

积分
16
发表于 2016-11-25 04:07:58 | 显示全部楼层
好棒!!!
回复

使用道具 举报

7

主题

34

帖子

192

积分

注册会员

Rank: 2

积分
192
发表于 2017-1-6 19:22:28 | 显示全部楼层
来一张正则思维导图:(非原创)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
欢迎关注博客: 生信客部落
回复 支持 反对

使用道具 举报

1

主题

33

帖子

247

积分

中级会员

Rank: 3Rank: 3

积分
247
发表于 2017-2-16 10:45:21 | 显示全部楼层
这个好棒 看后收获很大
人生若只如初见!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|关于我们|手机版|小黑屋|生信技能树    

GMT+8, 2017-5-24 15:55 , Processed in 0.037378 second(s), 33 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.