搜尋
首頁後端開發php教程php实战正则表达式(二):提取html元素

这篇文章通过提取html元素介绍了正则表达式中模式修饰符、贪婪匹配与非贪婪匹配、Unicode模式、环视等知识点。
在阅读这篇文章前最好把同系列文章php实战正则表达式(一):验证手机号先仔细阅读一遍。

基本提取

有这样一个表格

用户名 职业
Kobe Bryant 篮球运动员
Jay Chou 歌手、词曲创作人、制作人、演员、导演
Lionel Messi 足球运动员

它的源码如下:

<table>  <thead>    <tr><th>用户名</th><th>职业</th></tr>  </thead>  <tbody>    <tr>      <td>Kobe Bryant</td><td>篮球运动员</td>    </tr>    <tr>      <td>Jay Chou</td><td>歌手、词曲创作人、制作人、演员、导演</td>    </tr>    <tr>      <td>Lionel Messi</td><td>足球运动员</td>    </tr>  </tbody></table>

现在要提取

第一个元素。最简单的正则表达式应该是这样:

\s+.*

其中

  • \s是php实战正则表达式(一):验证手机号介绍过的字符组简记法中的一个,代表回车符、空格、制表符等空白字符

  • 量词+表示它所修饰的字符或字符组出现次数大于等于1

  • 点号字符.在正则表达式中是一个特殊的元字符,它可以匹配“任意字符”

  • 闭标签

中的斜线/在php的正则表达式中是模式分隔符,所以需要转义来表示斜线字符。

但实际上这样一个表达式是无法从上面的

中提取第一个元素的

这里主要的问题是在默认情况下点号字符.无法匹配换行符\n。有两个方法可以解决这个问题:

  • 使用模式修饰符s,正则表达式为/

    \s+.*/s或(?s) \s+.*。模式修饰符s的作用就是让点号字符.可以匹配换行符。
  • 用[\s\S]或[\w\W]或[\d\D]代替点号字符.来匹配所有字符,正则表达式为

    \s+[\s\S]*

    关于模式修饰符(Pattern Modifiers),这里需要详细介绍一下(点击这里查看php支持的所有模式修饰符)。模式修饰符可以改变正则表达式的一些默认规则,常用的模式修饰符有i、s、U、u等,我们在后面会用到它们中的一些,这里不展开介绍每个模式修饰符的作用,后面用到了再具体介绍。这里主要对比一下/.../{modifier}与...(?{modifier})...两种表示方法的区别。

    .*/s (?s).*
    模式修饰符 /.../{modifier} ...(?{modifier})...
    示例 /
    名称(php手册) 模式修饰符 模式内修饰符
    名称(《正则指引》) 预定义常量 模式修饰符
    作用范围 整个正则表达式 不在分组(子表达式)中时,对它后面的全部正则表达式起作用;如果在分组(子表达式)中,则对它分组中的剩余部分起作用。在没有分组,且放在整个正则表达式最前面的时候相当于/.../{modifier}
    支持程度 支持所有模式修饰符 支持部分模式修饰符
    其他编程语言 可能不支持 一般都支持

    从上面的gif中可以看到提取的结果中有三个tr,而不是只有一个。这是因为正则表达式中量词默认是贪婪匹配,在这里,.*会匹配一切字符,直到最后没有字符再向前回溯,回溯到

    中的最后一个时与正则表达式中的相匹配,从而完成整个匹配过程,最后的结果也就是包含了三个。

    可以使用模式修饰符U指定整个正则表达式为非贪婪模式,也可以使用非贪婪匹配量词指定某一个量词为非贪婪模式:

    • 指定整个正则表达式为非贪婪模式:

      • /

        \s+.*/Us
      • 或(?Us)

        \s+.*
      • 非贪婪量词:
        /

        \s+.*?/s

        完整的贪婪量词(匹配优先量词)与非贪婪量词(忽略优先量词)见下表:

        贪婪量词 非贪婪量词 限定次数
        * *? 可能出现,可能不出现,出现次数没有上限
        + +? 至少出现1次,没有上限
        ? ?? 出现0次或1次
        {m,n} {m,n}? 出现次数大于等于m,小于等于n
        {m,} {m,}? 至少出现m次,没有上限
        {0,n} {0,n}? 出现0次-n次

        提取包含指定内容的行

        假设我们想把表格中有关于运动员的记录都提取出来,我们可能会使用/

        .*运动员.*/s这样的正则表达式。

        这个表达式在Unicode编码环境下可以匹配出结果,但是在GBK环境下就未必了。我们可以通过模式修饰符u来指定Unicode模式:

        /

        .*运动员.*/us

        在Unicode模式下,我们甚至可以使用码值来代替汉字:

        /

        .*\x{8fd0}\x{52a8}\x{5458}.*/us

        php正则中使用\x{hex}的形式来表示Unicode字符的码值,使用码值的好处是可以结合字符组来表示一段范围,如[\x{4e00}-\x{9fff}]表示匹配所有汉字字符。

        上面的表达式可以匹配出结果,但是却不正确。我们可以看到,它匹配了整个字符串的第一个

        到最后一个。
        直觉上,我们是想正则表达式先去匹配“运动员”,然后向左寻找最近的一个,向右寻找最近的一个。但事实上,正则表达式是从左往右匹配的,即从开始寻找,整个正则表达式的匹配情况见下表(空白字符没有显示出来)。
        表达式 匹配值
        /
        .* 用户名 职业
        Kobe Bryant 篮球
        运动员 运动员
        .*
        Jay Chou 歌手、词曲创作人、制作人、演员、导演
        Lionel Messi 足球运动员
        /us

        这里两个.*匹配到的字符都比预期要多。第二个.*匹配字符比预期多的原因是正则表达式默认是贪婪匹配模式,它会匹配剩余字符串中的每个字符,直到字符串的末尾,然后再向前回溯到最后一个

        ,可以通过指定非贪婪匹配模式来解决这个问题。但是第一个.*匹配字符比预期多是正常现象,因为正则表达式是从左向右匹配的,表达式中的匹配字符串中第一个 ,后面的.*则匹配剩余的所有字符,直到字符串的末尾,然后再向前回溯到“运动员”。

        我们先看看使用非贪婪匹配时的结果:

        可以看到,第二个.*匹配的字符已经是我们想要的了。那么,对于第一个.*匹配字符比预期多这个问题怎么解决呢?

        如果仅使用到目前为止我的文章中介绍的知识,也是有方法可以解决的。我们可以先从左到右匹配出所有的行(

        ...),方法是使用php中的preg_match_all函数结合非贪婪匹配模式;然后再遍历每一行,过滤出其中包含“运动员”的行即可。

        当然,我们也可以通过纯粹的正则表达式来解决这个问题。如果有一定正则表达式使用经验的朋友可能很容易联想到排除型字符组,我们介绍过字符组[...],它表示在同一位置可能出现的字符。而排除型字符组则表示在同一位置不能出现的字符,它的形式是[^...],通过紧跟在开方括号[后面的^来表示排除型字符组。例如,[^\d]表示匹配的字符是除了数字以外的任意字符。
        如果有排除型子表达式,类似于(^

        )*,我们只需要指定第一个.*把 排除就行了。但是很遗憾,正则表达式中没有排除型子表达式或者说排除型分组。这种情况下,我们只能使用环视

        /

        (.(?! ))*运动员.*/Us

        环视(look-around)不匹配任何字符,用来“停在原地,四处张望”。上面的表达式使用了否定顺序环视,它的形式是(?!...)。具体对于(.(?!

        ))*来分析,每当.匹配了一个字符后,就向右看看,如果当前匹配字符的右边没有出现 就匹配成功。

        完整的环视有:

        名字 记法 含义
        肯定顺序环视 (?=...) 向右看看,右边出现了环视中的内容才匹配
        否定顺序环视 (?!...) 向右看看,右边不出现环视中的内容才匹配
        肯定逆序环视 (? 向左看看,左边出现了环视中的内容才匹配
        否定逆序环视 (? 向左看看,左边不出现环视中的内容才匹配

        由于上面的正则表达式有一个分组(子表达式),所以匹配的结果除了下标0,还有下标1,这里下标1的结果其实没有什么用,我们可以用之前介绍过的非捕获分组

        /

        (?:.(?! ))*运动员.*/Us

        我们的真正目的是提取所有包含“运动员”的行,而上面只提取了第一个,所以需要将preg_match函数换成preg_match_all。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
超越炒作:評估當今PHP的角色超越炒作:評估當今PHP的角色Apr 12, 2025 am 12:17 AM

PHP在現代編程中仍然是一個強大且廣泛使用的工具,尤其在web開發領域。 1)PHP易用且與數據庫集成無縫,是許多開發者的首選。 2)它支持動態內容生成和麵向對象編程,適合快速創建和維護網站。 3)PHP的性能可以通過緩存和優化數據庫查詢來提升,其廣泛的社區和豐富生態系統使其在當今技術棧中仍具重要地位。

PHP中的弱參考是什麼?什麼時候有用?PHP中的弱參考是什麼?什麼時候有用?Apr 12, 2025 am 12:13 AM

在PHP中,弱引用是通過WeakReference類實現的,不會阻止垃圾回收器回收對象。弱引用適用於緩存系統和事件監聽器等場景,需注意其不能保證對象存活,且垃圾回收可能延遲。

解釋PHP中的__ Invoke Magic方法。解釋PHP中的__ Invoke Magic方法。Apr 12, 2025 am 12:07 AM

\_\_invoke方法允許對象像函數一樣被調用。 1.定義\_\_invoke方法使對象可被調用。 2.使用$obj(...)語法時,PHP會執行\_\_invoke方法。 3.適用於日誌記錄和計算器等場景,提高代碼靈活性和可讀性。

解釋PHP 8.1中的纖維以進行並發。解釋PHP 8.1中的纖維以進行並發。Apr 12, 2025 am 12:05 AM

Fibers在PHP8.1中引入,提升了並發處理能力。 1)Fibers是一種輕量級的並發模型,類似於協程。 2)它們允許開發者手動控制任務的執行流,適合處理I/O密集型任務。 3)使用Fibers可以編寫更高效、響應性更強的代碼。

PHP社區:資源,支持和發展PHP社區:資源,支持和發展Apr 12, 2025 am 12:04 AM

PHP社區提供了豐富的資源和支持,幫助開發者成長。 1)資源包括官方文檔、教程、博客和開源項目如Laravel和Symfony。 2)支持可以通過StackOverflow、Reddit和Slack頻道獲得。 3)開發動態可以通過關注RFC了解。 4)融入社區可以通過積極參與、貢獻代碼和學習分享來實現。

PHP與Python:了解差異PHP與Python:了解差異Apr 11, 2025 am 12:15 AM

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

php:死亡還是簡單地適應?php:死亡還是簡單地適應?Apr 11, 2025 am 12:13 AM

PHP不是在消亡,而是在不斷適應和進化。 1)PHP從1994年起經歷多次版本迭代,適應新技術趨勢。 2)目前廣泛應用於電子商務、內容管理系統等領域。 3)PHP8引入JIT編譯器等功能,提升性能和現代化。 4)使用OPcache和遵循PSR-12標準可優化性能和代碼質量。

PHP的未來:改編和創新PHP的未來:改編和創新Apr 11, 2025 am 12:01 AM

PHP的未來將通過適應新技術趨勢和引入創新特性來實現:1)適應云計算、容器化和微服務架構,支持Docker和Kubernetes;2)引入JIT編譯器和枚舉類型,提升性能和數據處理效率;3)持續優化性能和推廣最佳實踐。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版