是否可以在preg_match中排除匹配字符串的一部分?

时间:2018-10-13 16:37:05

标签: php regex

当编写应该从特定div下载内容的脚本时,我想知道是否有可能以不包含在匹配结果中的方式跳过模式的某些部分。

例如:

<?php

$html = '
<div class="items">
    <div class="item-s-1827">
      content 1
    </div>
    <div class="item-s-1827">
      content 2
    </div>
    <div class="item-s-1827">
      content 3
    </div>
</div>
';

preg_match_all('/<div class=\"item-s-([0-9]*?)\">([^`]*?)<\/div>/', $html, $match);
print_r($match);

/*

Array
(
    [0] => Array
        (
            [0] => <div class="item-s-1827">
      content 1
    </div>
            [1] => <div class="item-s-1827">
      content 2
    </div>
            [2] => <div class="item-s-1827">
      content 3
    </div>
        )

    [1] => Array
        (
        [0] => 1827
        [1] => 1827
        [2] => 1827
    )

[2] => Array
    (
        [0] => 
  content 1

        [1] => 
  content 2

        [2] => 
  content 3

    )  ) */

是否可以省略class = \“ item-s-([0-9] *?)\”这样的方式,使结果不显示在$ match变量中?

2 个答案:

答案 0 :(得分:3)

通常,您可以在搜索字符串之前或之后声明带有肯定的lookbehinds /积极的lookaheads的字符串。在向后看的情况下,图案必须具有固定的长度,这与您的要求冲突。但幸运的是,还有一个强大的替代方案:您可以使用\K(使文本不使用正则表达式),请参见http://php.net/manual/en/regexp.reference.escape.php

  自PHP 5.2.4起,

\K可用于重置比赛开始。例如,模式foo\Kbar匹配“ foobar”,但是报告它已匹配“ bar”。 \K的使用不会干扰捕获的子字符串的设置。例如,当模式(foo)\Kbar与“ foobar”匹配时,第一个子字符串仍设置为“ foo”。

这是正则表达式(对此我做了一些其他更改),带有\K和积极的前瞻:

preg_match_all('/<div class="item-s-[0-9]+">\s*\K[^<]*?(?=\s*<\/div>)/', $html, $match);
print_r($match);

打印

Array
(
    [0] => Array
        (
            [0] => content 1
            [1] => content 2
            [2] => content 3
        )
)

答案 1 :(得分:1)

在PHP中解析HTML的首选方法是使用DomDocument加载HTML,然后使用DomXPath搜索结果对象。

更新

根据要提问的注释进行了修改,因此<div>类名只需以item-s-开头。

$html = '<div class="items">
    <div class="item-s-1827">
      content 1
    </div>
    <div class="item-s-18364">
      content 2
    </div>
    <div class="item-s-1827">
      content 3
    </div>
</div>';

$doc = new DomDocument();
$doc->loadHTML($html);
$xpath = new DomXPath($doc);
$divs = $xpath->query("//div[starts-with(@class,'item-s-')]");
foreach ($divs as $div) {
    $values[] = trim($div->nodeValue);
}
print_r($values);

输出:

Array ( 
    [0] => content 1 
    [1] => content 2
    [2] => content 3 
)

Demo on 3v4l.org