Perl Learning 6 Regular Expression


正则表达式在Perl里面通常也叫做模式(pattern)是用来表示匹配(或不匹配)某个字符串的特征模板。注意不要把正则表达式和shell的“文件名匹配模式”(又称为glob,文件名通配)混为一谈。在Unix shell中键入*.pm来匹配所有以.pm结尾的文件就是典型的文件名通配。

简单匹配模式:若模式匹配的对象是$_的内容,只要把模式写在一对斜线中就行。


Unicode属性:Unicode字符能够理解自身含义,它们不只是简单的字节序列。每个字符除了字节组合之外,还附带着属性信息。若要匹配某项属性,只需要把属性名放入\p{property}里面。比如有很多字符属于空白符(whitespace),相应的属性名为Space,所以要匹配带有这类属性的字符,可以用\p{Space}表示。我们还能匹配不包含特定属性的字符,只要把小写的p改为大写,就表示否定意义,匹配指定属性以外的字符。

 

元字符:点号(.)是能匹配任意一个字符的通配符,换行符(“\n”)除外。注意:在任何元字符前面加上反斜线,就会使它失去元字符的特殊作用。

 

简单的量词: 星号(*)用来匹配某条目零次或多次的。.*会匹配任意字符零次到无限多次。加号会匹配前一个条目一次以上:/fred+barney/会匹配在fredbarney之间用空格隔开并且只用空格隔开的字符串(空格不是元字符)。问号(?)表示前一个条目是可有可无的。

 

模式分组:小括号的作用是对字符串分组,模式/(fred)+/会匹配项fredfredfred这样的字符串。圆括号同时也使得重新使用某些字符串成为可能。我们可以用反向引用来引用圆括号中的模式所匹配的文字,这个行为我们称为捕获组。反向引用的写法是在反斜线后面接上数字编号,比如\1\2这样。相应的数字表示对应顺序的捕获组。

使用圆括号包围的点号可以匹配任意非换行字符。我们可以用反向引用\1来再次匹配刚刚在圆括号中匹配的任意字符:



(.)\1表明需要匹配连续出现的两个同样的字符。反向引用不必紧接在对应的捕获组括号后面。下面的模式会匹配y后面的4个连续的非换行符,并用\1反向引用表示匹配d后也出现这4个字符的情况:



也可以用多个括号来分成多组,每组都可以有自己的反向引用。我们可以用括号定义一个非换行字符的捕获组,后面跟着一个非换行字符的捕获组。然后用反向引用\2\1来构成有趣的回文模式,比如abba



Perl 5.10开始支持一种新的反向引用写法。不再只是简单的用反斜线和组号,而是用\g{N}这种形式。其中N是想要反向引用的组号。

$_ = "aa11bb";
if (/(.)\g{1}11/){
	print "It matched 11! \n";
}

\g{N}的写法的额外好处是,我们甚至可以用负数。相比指定捕获组的绝对编号,相对反向引用会更加有趣。这样我们可以用-1来做同样的事情:

$_ = "aa11bb";
if (/(.)\g{-1}11/){
	print "It matched 11! \n";
}<pre name="code" class="plain">

 

这样若要在模式中加入更多的内容,就不必总是修改反向引用的编号了。因为要加入另外一个捕获组,就会导致所有绝对编号的反向引用失效,而相对反向引用则不会,因为它使用的是相对于自己的位置,而不是绝对编号:

$_ = "xaa11bb";
if (/(.)(.)\g{-1}11/){
	print "It matched 11! \n";
}

择一匹配:竖线(|通常可以读成或,意思是要么匹配左边的内容,要么匹配右边的内容。现在可以使用/fred(|\t)+barney/这样的模式来匹配fredbarney之间出现一次以上空格、制表符或两者混合的字符串。加号表示重复一次或者更多,每次只要有重复,(|t)就可能匹配空格或制表符。若要求fredbarney之间的字符必须都一样,你可以把上述模式改成/fred(+|\t+barney/),这样,中间的分隔符就一定得全是空格或全是制表符。

 

字符集:指的是一组可能出现的字符,通过写在方括号表示。它只匹配单个字符,但可以是字符集中列出的任意一个。我们可以用连字符(-)表示始末范围,这样[a-zA-Z]可以匹配52个大小写字母中的任意一个。

 

字符集的简写。表示任意一个数字的字符集的简写是\d

$_ = "The Hal-9000 requires authorization to continue";
if (/Hal-[\d]+/){
	 print 'The string mentions some model of Hal computer.';
}


当我们需要严格按照ASCII的范围来匹配数字字符时,可以选用\a,写在正则表达式末尾。\s能匹配任意空白符,所以效果大抵等同于Unicode属性\p{Space}\R能匹配任意一种断行符。

反义简写:引入它们的大写版本来表示否定意义。这些简写既可以作为模式里独立的字符集,也可以作为方括号里字符集的一部分。/[\dA-Fa-f]+/可以用来匹配十六进制数字。[\d\D]表示任何数字非数字,也就是说,它会匹配任意字符。




第一题:

<span style="font-size:12px;">$_ = <STDIN>;
if (/fred/){
	print;
}</span>

俺写的只能一行一行判断,答案里面加上了while循环

while(<>){
	if(/fred/){
		print;
	}
}

就是能够直接识别你当前输入的行中是否有fred,有则复制没有则继续。


我们发现Fred没有接受,而后两者接受了,正则表达式对大小写还是很敏感的。


习题二:改为能接受Fred的话,将第一题中的/fred/改为/[f|F]red/即可

习题三:

while(<>){
	if(/\./){
		print;
	}
}


发现输入Mr.Slate的时候会输出。

习题四:

while(<>){
	if (/[A-Z]+/){
		print;
	}
}

该代码对全大写的单词也会打印。在[A-Z]后面再加上[a-z]即可

第五题:

while(<>){
	if (/(\S)\g{-1}/){
		print;
	}
}


第六题:

while(<>){
	if(/[fred.*wilma]/){
		print;
	}
}


我看了下答案,它是这么写的(/wilma.*fred|fred.*wilma/)。我觉得比我写的要麻烦些。但是经过验证我发现我写的还是有问题,因为我输入fred的时候也可以打印,不符合题目要求。[]的使用只是提供了一个集合。


总结:这段时间一直在忙小学期,做一个推荐系统,我们的框架是由php+python搭出来的,之后等成绩出来了就把我们的项目讲一下。之后的日子就继续学perl以及Verilog和VTR


正则表达式在 Perl 里面通常也叫做模式 (pattern) 是用来表示匹配(或不匹配)某个字符串的特征模板。注意不要把正则表达式和 shell 的“文件名匹配模式”(又称为 glob ,文件名通配)混为一谈。在 Unix shell 中键入 *.pm 来匹配所有以 .pm 结尾的文件就是典型的文件名通配。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值