注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Bioinformatics home

 
 
 

日志

 
 

perl短路匹配和多行匹配  

2009-05-11 16:47:41|  分类: Perl |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

if($c=~/\<p id=\"aug\"\>(.+?)\<\/p\>/s)     # 短路匹配(.+?)\     和多行匹配   s
{
  $str=$1;
  $str=~s/\<(.+?)\>//g;
  $str=~s/(\d+)//g;
  $str=~s/\&(\S+)\;//g;
   $str=~s/\n//g;
  print "person: ".$str."\n";
  }

 

PCRE 之 ?> 锁定成功匹配的分组结果
标题有点拗口,寒一个的说。先看个不涉及到 ?> 的例子

my $txt = 'AK74';
$txt =~ /((\w*)(\d+))/i;
print $1;

打印结果是 AK74

Regex 引擎首先用 \w* 去匹配字符串 AK74,* 修饰符的最长匹配原则导致 \w* 匹配到了整个字符串 AK74,接着 \d+ 上场匹配,由于 + 修饰符要求至少匹配一次,为大局考虑,\w* 不得不吐出一个已匹配到的字符 4 以满足 \d+ 的要求,所以最后结果就是 \w* 匹配到 AK7 而 \d+ 也成功匹配到了字符 4

如果我们期望前面的分组匹配成功之后,无论其后匹配状况如何都不再吐出已匹配的结果,那就可以使用 ?> 将分组中已匹配成功的结果锁定。

my $txt = 'AK74';
$txt =~ /((?>\w*)(\d+))/i;
print $1;

运行上面的代码将收到“使用了未初始化值”的错误提示。

同未使用 ?> 的 Regex 表达式一样,\w* 首先匹配到了整个字符串 AK74,接着 \d+ 上场匹配,+ 要求 \w* 至少吐出一个字符以满足匹配,但是 ?> 却自私的将 \w* 的匹配结果锁定,即 \w* 并没有吐出任何字符,仍然保留整个 AK74 字符串,结果导致 \d+ 匹配失败,最终整个 Regex 表达式匹配失败,所以打印 $1 时收到了错误提示。

显而易见 ?> 并不锁定失败的匹配结果,失败的匹配或空匹配也没什么需要锁定的内容

my $txt = 'AK74';
$txt =~ /((?>(MP5)*)(\d+))/i;
print $1;

打印结果是 74

因为 $txt 值中并不包含 MP5 字符串,所以一开始,(MP5)* 就匹配失败,接着 \d+ 上场匹配,跳过 AK 后,成功获得字符串 74,由于 * 修饰符允许空匹配,所以整个 Regex 表达式匹配成功。

ps.  昨天把脖子拧了,睡觉还落枕,呀呀个呸的,今天只歪起脑壳做人了
posted on 2008-03-15 08:10:32 by Anrs  评论(0) 阅读(2533)
PCRE 基础之“最长匹配”、“最短匹配”
量词的最长匹配原则

*, + 和 {m, n} 这样的量词都遵循最长匹配原则,也就是说可能出现多种匹配情况时,Regex 总是选择最长的匹配结果。

my $txt = 'javascript and ecmascript and perlscript';
$txt =~ /(.*)script/i;
print $1;

打印结果是 javascript and ecmascript and perl

.*script 可能的匹配结果包括
javascript
javascript and ecmascript
javascript and ecmascript and perlscript
而第三种匹配结果是最长的,所以 (.*) 的内容就包括了 javascript and ecmascript and perl,这就是所谓的最长匹配原则。同理,

my $txt = 'VeryVeryVery';
$txt =~ /((?:very){1,3})/i;
print $1;

打印结果是 VeryVeryVery,因为这个匹配结果也是最长的。

可以用 ? 忽略最长匹配原则,因为 ? 总是告诉 Regex 引擎“我要最短匹配”

my $txt = 'VeryVeryVery';
$txt =~ /((?:very){1,3}?)/i;
print $1;

因为 ? 忽略了最长匹配原则,所以打印结果是 Very

再看一下极端情况下的 ? 最短匹配

my $txt = 'VeryVeryVery';
$txt =~ /((?:very){0,3}?)/i;
print $1;

打印结果是空字符串,因为 {0,3} 的最短匹配就是空字符串,一定一定一定要注意的是匹配空并不等价于匹配失败,空字符串也是一种有效的成功匹配的结果。
posted on 2008-03-13 08:17:36 by Anrs  评论(0) 阅读(1909)
PCRE 基础之“最早匹配”
昨个有朋友问我 s/a|b/c/i 为什么只能替换 a 或者 b 而不能同时将 a, b 都替换成 c?
关于这个问题,最简单的回答就是“忽略了最早匹配原则”

首先解释一下什么是“最早匹配原则”

my $txt = 'ksharp kplus';
$txt =~ s/k/c/i;
print $txt;

打印结果是 csharp kplus

根据 Perl Regex “优先选择最早出现的匹配结果”原则
/k/ 会匹配 $txt 中单词 ksharp 中打头的 k,因为这个 k 是整个字符串中最早匹配 /k/ 的结果,这也就是所谓的“最早匹配原则”

多选分支中的匹配也符合该原则
$txt = 'csharp cplus ruby perl java';
$txt =~ s/java|cplus/lisp/i;
print $txt;

打印结果是 csharp lisp ruby perl java

虽然 /java|cplus/ 中 java 出现在 cplus 之前,但是 Regex 会在每一个位置尝试所有的匹配,也就是说每一次 Regex 引擎都会同时尝试 /java/ 和 /cplus/,根据“优先选择最早出现的匹配结果”原则,当匹配 /cplus/ 成功后,引擎就会退出,而不再尝试匹配 /java/,这就有点类似于 open(FH, $file) || die 'error' 中的 || 短路操作,当 open 成功的话,就不再执行 die 操作了。

这还有一个稍微特殊一点的例子来说明最早匹配原则
$txt = 'abcd';
$txt =~ s/a|ab|abc|abcd/r/i;
print $txt;

打印结果是 rbcd

  评论这张
 
阅读(1604)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017