【问题标题】:PHP Regular expression return submatches as arrayPHP正则表达式将子匹配返回为数组
【发布时间】:2014-06-04 16:56:48
【问题描述】:

我有一个关于正则表达式的问题。

我想要做的是只使用一个正则表达式来匹配字符串的一部分并取出里面的内容。不知道怎么解释,就写个例子吧

要解析的示例 html

<div class="test">
    <span>a</span>
    <span>b</span>
    <span>c</span>
    <span>d</span>
</div>
<div class="test2">
    <span>aa</span>
    <span>bb</span>
    <span>cc</span>
    <span>dd</span>
</div>

我只想 preg_match(_all) 跨越 .test 中的值

通常情况下,我会使用

preg_match('/<div class="test">(.*?)<\/div>/', $html, $matches)
preg_match_all('/<span>(.*?)<\/span>/',  $matches[1],  $matches2)

然后使用另一个 preg_match_all 来获取值。

但是,我想知道是否有一种方法可以在一个模式中创建一个子模式,该模式会自动首先匹配 div,然后是所有跨度,并将结果作为数组返回。

这样的事情可能吗?我在任何地方都找不到它。也许我不知道它在技术上是怎么称呼的。

编辑: 我想获得的输出(更改的数据样本),但只有一次 preg_match 或 preg_match_all 调用

array(
    'a',
    'b',
    'c',
    'd',
);

【问题讨论】:

    标签: php arrays regex function dom


    【解决方案1】:

    使用DOMParser 而不是使用正则表达式..

    $dom = new DOMDocument;
    $dom->loadHTML($html);
    foreach ($dom->getElementsByTagName('div') as $tag) {
        if ($tag->getAttribute('class') === 'test')
        {
            foreach($tag->getElementsByTagName('span') as $stag)
            {
            $val[]=$stag->nodeValue;
            }
        }
    }
    print_r($val);
    

    使用 XPath 查询..(相同)

    $xpath = new DOMXpath($dom);
    $elements = $xpath->query("*/div[@class='test']/span");
    foreach($elements as $v)
    {
        $arr[]=$v->nodeValue;
    }
    print_r($arr);
    

    OUTPUT :

    Array
    (
        [0] => a
        [1] => b
        [2] => c
        [3] => d
    )
    

    Working Demo - Normal DOM Way

    Working Demo - XPath Way

    【讨论】:

    • 不错的解决方案,但我正在从网站上删除一些,这并不总是相同的。所以它可以不同
    • 即使在这种情况下,DOM 也是正确的处理方式。你能发布你的预期输出吗?
    • 我知道 DOM。但我想更多地知道这样的正则表达式是否可行。如果存在这样的正则表达式,这个问题就更多了。将使用预期的输出编辑 qeustin
    • 很好。同时,请阅读我们的 Jeff Atwood 撰写的 article。它说明了为什么不应该使用 Regex 来解析 HTML。
    • 大约有 60 种不同的模板。不同的定位取决于入口类型。我必须从缓存中取出数据,因为整个数据库都丢失了,缓存只是剩下的。只有地址/类型/名称等部分相同。为每个模板编写 DOM walker 需要很长时间。脚本不会在日常工作中使用,也不会以任何形式分发。因此,这是一次脚本获取数据,将解析 600 页并将被删除。这就是为什么我决定使用 preg_match 而不是 DOM。
    【解决方案2】:

    这是你想要的吗:

    /&lt;span&gt;([^&lt;]*)&lt;\/span&gt;/preg_match_all

    演示:http://regex101.com/r/yD6gM0

    【讨论】:

    • 我只想匹配来自 div 的 .test 而不是来自 .test2 的匹配
    猜你喜欢
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    相关资源
    最近更新 更多