IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

PHP 正则里面的两个重要技巧

Michael`s blog 2012-05-04 00:03:26 累计浏览 4,309 次
本机暂存

正则用了好些年,有两个东西总结出来是在web开发中非常有用的,尤其在抓取、代码分析中经常用到。

1. .* 的贪吃性

我们用 /\*.*\*/ 去和字符串 /* first comment */ not comment /* second comment */ 匹配会失败,因为由于 .* 项目的贪吃性,会匹配成整个字符串,于是就会匹配失败,不过,如果在后面加一个问号数量符,则会停止贪吃性,而变成匹配尽可能少的数目,因此模式 /\*.*?\*/ 就会正确匹配。各种数量符的含义并没有改变,只是优先的匹配数目。不要将问号的此用法和其自己作为数量符的使用混淆。因为有两种用法,有时可以两个一起出现,例如 \d??\d 会优先匹配一个数字,但如别无选择也可以匹配两个以使剩余模式匹配。

如果设定了 PCRE_UNGREEDY 选项(此选项 Perl 中没有)则数量符默认不是贪吃型的,但是在个别模式后加上一个问号可以将其变成贪吃型的。换句话说,这可以反转默认的行为。

后面跟上一个 + 的数量符是“占有性”(possessive)的。它会匹配尽可能多的字符而不管剩余的模式。因此 .*abc 可以匹配 “aabc” 但是 .*+abc 就不会,因为 .*+ 已经匹配了整个字符串。自 PHP 4.3.3 起可以用占有性数量符可以来加快处理过程。

2. ()子模式的不捕获

如果将字符串 “the red king” 来和模式 the ((red|white) (king|queen))
进行匹配,捕获的子串为 “red king”,”red” 以及 “king”,并被计为 1,2 和 3。

简单的括号实现两种功能的事实不总是有帮助的。经常有需要一组子模式但不需要捕获的时候。如果左括号后面跟着 “?:”,子模式不做任何捕获,并且在计算任何之后捕获的子模式时也不算在内。例如,如果用字符串 “the white queen” 去和模式 the ((?:red|white) (king|queen)) 匹配,捕获的子串是 “white queen” 和 “queen”,并被计为 1 和 2。

因此,最完美的匹配网页中图片 src 部分的正则表达式处理如下:

$str='<p style="padding: 0px; margin-top: 0px; margin-bottom: 0px; line-height: 200%;"><img border="0" src="upfiles/2009/07/1246430143_4.jpg" alt=""/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 0px; line-height: 200%;"><img border="0" src=\'upfiles/2009/07/1246430143_3.jpg\' alt=""/></p><p style="padding: 0px; margin-top: 0px; margin-bottom: 0px; line-height: 200%;"><img border="0" src="upfiles/2009/07/1246430143_1.jpg" alt=""/><img width="280" height="187" alt="" class="imgloading" original="http://s.yoututuan.com/team/2011/1206/13231497847660.jpg" src="http://s.yoututuan.com/team/2011/1206/13231497847660.jpg" style="display: block; ">';
 
$pattern="/<img.*?src=['|\"](.*?(?:\.(?:gif|jpg)))['|\"].*?[\/]?>/i";
preg_match_all($pattern,$str,$match);
 
print_r($match);

以上代码将输出如下内容:

Array
(
    [0] => Array
        (
            [0] => <img border="0" src="upfiles/2009/07/1246430143_4.jpg" alt=""/>
            [1] => <img border="0" src='upfiles/2009/07/1246430143_3.jpg' alt=""/>
            [2] => <img border="0" src="upfiles/2009/07/1246430143_1.jpg" alt=""/>
            [3] => <img width="280" height="187" alt="" class="imgloading" original="http://s.yoututuan.com/team/2011/1206/13231497847660.jpg" src="http://s.yoututuan.com/team/2011/1206/13231497847660.jpg" style="display: block; ">
        )

    [1] => Array
        (
            [0] => upfiles/2009/07/1246430143_4.jpg
            [1] => upfiles/2009/07/1246430143_3.jpg
            [2] => upfiles/2009/07/1246430143_1.jpg
            [3] => http://s.yoututuan.com/team/2011/1206/13231497847660.jpg
        )

)

同分类推荐文章

  1. Vibe新开源项目 - Vaala AI Gateway (2026-05-17 02:10:19)
  2. SmartPerfetto 架构文章 Q&amp;A:8 个深度技术问答 (2026-04-10 11:00:00)
  3. 让 AI 把我的 PHP 博客重写成 Go (2026-03-27 18:33:54)

查看更多 后端 文章 →

建议继续学习

  1. 使用gettext来支持PHP的多语言 (累计阅读 39,192)
  2. vim几个小技巧(批量替换,列编辑) (累计阅读 37,356)
  3. WordPress插件开发 -- 在插件使用数据库存储数据 (累计阅读 29,092)
  4. Paypal接口详细代码(PHP版,非API接口) (累计阅读 19,347)
  5. 我的PHP,Python和Ruby之路 (累计阅读 13,070)
  6. include(“./file.php”)和include(“file.php”)区别 (累计阅读 12,728)
  7. 15个最好的免费开源电子商务平台 (累计阅读 12,466)
  8. Redis消息队列的若干实现方式 (累计阅读 12,007)
  9. 到底什么是MVC? (累计阅读 11,711)
  10. 整理了一份招PHP高级工程师的面试题 (累计阅读 11,476)