正则表达式在php中返回空数组,即使正则表达式是正确的

时间:2013-06-20 20:16:40

标签: php regex

这是我的正则表达式:

$pattern_new="/<td>(\n|\s)*?(<span(\n|\s|.)*?<\/strong>(\n|\s)*?\$(?<price>([0-9.]*)).*?)\$(.*?)(\n|\s)*?</";

这是我必须进行匹配的示例模式:

<td><strong>.zx</strong></td><td><span class="offer"><strong>xscre:<br></strong>$299 xxxxx&x;xx<span class="fineprint_number">2</span></span><br>de&ea;s $399</td><td>zxcddcdcdcdc</td></tr><tr class="dark"><td><strong>.aa.rr</strong></td><td><span class="offer"><strong>xscre:<br></strong>$99 xxxxx&x;xx<span class="fineprint_number">2</span></span><br>de&eae;s $199</td><td>xxxx</td></tr><tr class="bar"><td colspan="3"></td></tr><tr class="bright"><td><strong>.vfd</strong></td><td><span class="offer"><strong>xscre:<br></strong>$99 xxxxx&x;xx<span class="fineprint_number">2</span></span><br>du&ee;s $199</td><td>xxxxxxxx</td></tr><tr class="dark"><td><strong>.qwe</strong></td><td><span class="offer"><strong>xxx<br></strong>$99 xxxc;o<span class="fineprint_number">2</span>

以下是我在PHP中所做的事情

$pattern_new="/<td>(\n|\s)*?(<span(\n|\s|.)*?<\/strong>(\n|\s)*?\$(<price>)*([0-9.]*).*?)\$(.*?)(\n|\s)*?</";
$source = file_get_contents("https://www.abc.com/sources/data.txt");
preg_match_all($pattern_new, $source, $match_newprice, PREG_PATTERN_ORDER);
echo$source;
print_r($match_newprice);

$match_newprice返回一个空数组。

当我使用像myregextestersolmetra.com这样的正则表达式测试时,我得到了一个完美匹配,没有任何问题,但是当我使用php preg_match_all进行匹配时,它正在返回一个空数组。我增加了pcre.backtrack_limit,但仍然是同样的问题。 我似乎不明白这个问题。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

我假设您正在尝试为<price...执行非捕获组,但您错过了:。或者你应该拿出问号。如果price组是可选的,请尝试下面的正则表达式。您应该使用以下网站来帮助您使用正则表达式。我发现它非常有帮助。

<td>(\n|\s)*?(<span(\n|\s|.)*?<\/strong>(\n|\s)*?\$(<price>)*([0-9.]*).*?)\$(.*?)(\n|\s)*?<

Regular expression image

Edit live on Debuggex

在上面的示例中,您的第一个匹配将具有以下捕获:

0: "<td><span class="offer"><strong>xscre:<br></strong>$299 xxxxx&x;xx<span class="fineprint_number">2</span></span><br>de&ea;s $399<"
1: ""
2: "<span class="offer"><strong>xscre:<br></strong>$299 xxxxx&x;xx<span class="fineprint_number">2</span></span><br>de&ea;s "
3: ">"
4: ""
5: ""
6: "299"
7: "399"
8: ""

这是你在找什么?

答案 1 :(得分:1)

PHP的另一个问题与此相关:

<?php
echo "\$".PHP_EOL;
echo '\$'.PHP_EOL;

结果:

$
\$

...与双引号字符串一样,$预计表示变量的开头,如果你的意思是$,则需要转义。在你的正则表达式和&amp;它可能会很好(虽然没有仔细看过,你可能想要使用/x选项&amp;添加一些格式化空格/注释,如果你需要从现在开始半年后调试它)。

答案 2 :(得分:1)

这样做的好方法:

$oProductsHTML = new DOMDocument();
@$oProductsHTML->loadHTML($sHtml);

$oSpanNodes = $oProductsHTML->getElementsByTagName('span');

foreach ($oSpanNodes as $oSpanNode) {
    if (preg_match('~\boffer\b~', $oSpanNode->getAttribute('class')) &&
        preg_match('~\$\K\d++~', $oSpanNode->nodeValue, $aMatch) )
    {
        $sPrice = $aMatch[0];
        echo '<br/>' . $sPrice;
    }
}

$sHtml代表你的字符串。

我相信你可以用XPath缩短它。

糟糕的方式:

$sPattern = '~<span class="offer\b(?>[^>]++|>(?!\$))+>\$\K\d++~';
preg_match_all($sPattern, $sHtml, $aMatches);

print_r ($aMatches[0]);

注意:\d++可以替换为\d++(?>\.\d++)?以允许十进制数字。