网站开发日志

2008年10月4日星期六

分享家:Addthis中国

Perl Regular Expressions (Perl 正则表达式)

我现在主要用PHP来写代码,当用到Regular Expressions的时候,就想到了我以前常用到的Perl Regular Expressions。虽然二者是使用方法所不同的,但是字符串匹配的规则是大体相通的,而且PHP兼容Perl的匹配规则(Pattern)。因此,我想先把Perl的正则表达式回顾总结一下。(参考:Steve Litt's Perls of Wisdom)

正则表达式的作用:

1. 判断字符串是否和一个特定字符或字符串匹配

  • $string =~ m/sought_text/;  #如果这个表达式成立,那么$string里就含有特定字符'sought_text'。

2. 选择字符串里的特定部分

  • $string =~ m/whatever1(sought_text)whatever2/;
  • $soughtText = $1;  #如果上面的表达式成立,那么$1就是'whatever1'和'whatever2'之间的那部分

3.字符串替换/翻译

  • $string =~ tr/originaltext/newtext/; 把字符串里'orignialtext'用'newtext'来代替

常用通配符和重复方法:

.   匹配任意字符 (除了换行符"\n")
^ 表示字符开始的空字符
$ 表示字符结束的空字符
\w  匹配任意(文字和数字)字母和下滑线
\W  匹配非任意(文字和数字)字母和下滑线的字符
\s  匹配空格符
\S  匹配非空格符

\d  匹配数字
\D  匹配非数字
\t  匹配'tab'键值
\n  匹配换行符
\r  品牌回车键
*      匹配0次或者多次
+      匹配一次或者多次
?      匹配0次或者一次
{n}    刚好匹配n次
{n,}   匹配n次以上,包含n
{n,m}  匹配n次以上,但是不超过m次

例子:

$string =~ m/\s*rem/i;   
#如果以上表达式成立,那么$string可以是以任意个空字符开始然后紧跟着非空字符可以为
#'rem'或者'REM'(不分大小写)
$string =~ m/^\S{1,8}\.\S{0,3}$/;
#以上表达式用来匹配1到8个的非空字符紧跟着一个'.',然后再紧跟着0-3个的非空字符。
#比如说'abcd.', 'a.34s',但是不匹配'.12dg','.123',等等。
匹配组, group()
如果我们想对一组字符进行匹配,我们可以用()。
例子:
if($string =~ m/(A|E|I|O|U|Y|a|e|i|o|u|y)/)
  {print "String contains a vowel!\n"}
#以上判断字符串是否包含元音
if($string =~ m/^(Clinton|Bush|Reagan)/i)
  {print "$string\n"};
#以上判断字符串是否已Clinton,Bush,Reagan中一个开头,不分大小写

匹配单一字符,character classes []

如果我们想匹配一组字符的中一个,我们可以用[]。

例子:

if($string =~ /[AEIOUYaeiouy]/)
  {print "String contains a vowel!\n"}
#这等同于上面的提到的组匹配,但是你会发现用'[]'要简介许多
if($string =~ m/(A|E|I|O|U|Y|a|e|i|o|u|y)/)
  {print "String contains a vowel!\n"}
if($string =~ /[^AEIOUYaeiouy]/)
  {print "字符串没有包含任何元音字母"}
#注意:上面这个例子中'^'不是表示起始空字符,而是表示'非'
if($string =~ m/^[A-E]/)
  {print "字符串是以A-E中的任何一个字母开头的\n"}
#注意:上面这个例子中'^'表示起始空字符

字符串替代 s

例子:

$string =~ s/少儿上网/61dh\.com/;
#把字符串里的'少儿上网'用61dh.com来代替。
注意:因为'.'表示任意字符,所以当我想表示'.'这个特殊字符时,可以用'\.'来表示。

字符串翻译 tr

和字符串替代比较相似,但是也有它独特的地方:把一组字符串的字符一一对应的替换。

例子:

$string =~ tr/[a-z]/[A-Z]/;
#把小写字母转换成大写字母
$string =~ tr/[六,一,导,航]/[6,1,d,h]/;
#把'六一导航'翻译成'61dh'

贪婪匹配和不贪婪匹配

Perl的正则表达式通常是贪婪匹配的,也就是说它尽量匹配更多的字符。这么说比较抽象,让我们看例子:

my($text) = "mississippi";
$text =~ m/(i.*s)/;
print $1 . "\n";
#'*'表示匹配0个或者多个,因为Perl比较贪心,所以匹配结果是’ississ'
$text =~ m/(i.?s)/;
print $1 . "\n";
#'*'表示匹配0个或者一个,同样Perl尽量去匹配多,所以结果是'iss'

如果想找到字符串里第一次出现'i'和's'的情况。也就是所谓的不贪婪匹配。我们可以同时使用'*'和'?'。

例子:

my($text) = "mississippi";
$text =~ m/(i.*?s)/;
print $1 . "\n";
#这下结果为'is'

补充(11/6/08):需要匹配多行的字符串,可以使用“smi”后缀修饰。例如:

$a = '<{LIST(10011002,10,0,0)}>
<tr>
<td width="100"> </td>
<td> </td>
<tr>
<{/LIST}> ';
if ($a =~ /<{[^}]+}\>(.+)\<{[^}]+}>/smi){
   print "yes";
}

标签:

相关文章:

4 条评论:

  • 请问正则表达式前面的m或者tr表示的是什么?

    作者 Anonymous freefrank, 时间 2008年10月6日 下午1:20  

  • 1. m是match,也就是匹配的意思
    例子:
    my($text) = "mississippi";
    $text =~ m/(i.*s)/;
    print $1 . "\n";
    #意思是在$text字符串里,把和(i.*s)匹配的部分取出。

    2. tr是translate, 也就是翻译的意思
    例子:
    my $string = "abc";
    $string =~ tr/[a-z]/[A-Z]/;
    #意思是把$string里的小写字母转换成大写字母,得到ABC。

    作者 Anonymous Adam, 时间 2008年10月7日 上午11:59  

  • 我对用英文写perl script 很熟。但我没弄清楚如何用Perl来处理中文文件。比如我有一份中文text文件,我如何写一个Perl script来parse它。
    从您的例子
    $string =~ s/少儿上网/61dh\.com/;
    似乎可以将中文字encode进去。
    不知您是否可以提供一个完整的script例子?
    谢谢!

    Fred

    作者 Anonymous Anonymous, 时间 2008年12月28日 下午2:30  

  • Fred:

    Perl 用的是UTF-8。如果你的终端用的是UTF-8字符集,你可以直接使用中文。

    如果你用的是GB2312, 你可以先进行编码转换,
    例如:
    $a 是GB2312 编码的字符串,
    $b = decode("GBK", $a); 或者 $b = encode("UTF-8", $a);
    这样得到的$b就是UTF-8编码,然后再对$b进行处理了

    作者 Anonymous Adam, 时间 2008年12月29日 下午9:59  

发表评论

指向此帖子的链接: