【问题标题】:Regex fails to match for no obvious reason正则表达式没有明显的原因无法匹配
【发布时间】:2010-07-03 11:24:40
【问题描述】:

考虑以下两个正则表达式 sn-ps 和它应该匹配的虚拟 HTML:

显然,在获得更多声誉之前,我只能发布一个链接,因此下面的链接包含我上面引用的三个链接:

http://pastebin.com/Qj1uxfdk

如果有人想知道的话,两个 sn-ps 之间的区别是在 sn-p 的一半左右被删除的(((.{2,20}?), (.{2,20}?))?)

第一个 sn-p 与文本不匹配,但第二个匹配,我不知道为什么。我尝试在其位置放置一个应该匹配任何内容的虚拟表达式(例如(.{1})?),但它仍然无法匹配它,但是当我删除它时,它突然又匹配了。

在过去的 4 个小时里,我一直在用这种愚蠢的表达方式苦苦挣扎,我快要崩溃了。有人可以帮忙吗?

【问题讨论】:

  • 我在 pastebin 上看不到任何东西。你有机会在这里发布事实吗?
  • 您可以通过缩进四个空格来发布代码,甚至是 HTML。我看了你的链接,正则表达式是不可读的,因为 sn-ps 包含 HTML。
  • 请发布您想要匹配的示例字符串,然后直接粘贴您已有的正则表达式。据我所知.{2,20}? 没有多大意义。那应该捕捉什么?
  • 不应使用正则表达式解析 HTML。它会让可爱的小猫死去。

标签: php regex pcre


【解决方案1】:

非常抱歉,我知道由于各种原因,这个答案不会受到任何人的赞赏,但无论如何,我觉得我必须这样说。

在我看来,您可能使用了错误的工具。我建议您使用真正的解析器,它旨在解析 (x)html/xml。我认为,html 包含的微妙之处远比你用正则表达式所能捕捉到的要多得多。我自己已经很长时间没有编写任何 php,但我确信它有必要的工具来为您进行解析 (maybe this?)。

当然,自己做所有事情是令人兴奋的,但利用已经为您完成(和测试)的东西更实际。

我希望,你会记住这一点。

PS:是的,我知道,通常的“不要使用正则表达式解析 xml”语句非常陈旧/平庸,但它并不能阻止它在大多数情况下是正确的。

【讨论】:

  • 恭喜,你说服我改用这种方式。感谢您对它很好,而不是告诉我“LOL UR DOIN IT RONG”。
【解决方案2】:

既然您似乎知道在解析 HTML 时,RegEx 并不是真正的东西,
你为什么还要尝试..?

例如,DOM 并不像您想象的那么难;
在 HTML 中获取所有 td 的基本示例:

$html = <<< EOL
<tr><td nowrap class="border_on_rbl"><a href="employee_view.html?employee_id=1337">bloblaw</td><td nowrap class="border_on_rb">Loblaw, Bob</b></td><td nowrap class="border_on_rb">Lawyer</td>
<td nowrap class="border_on_rb">Legal</td>
<td nowrap class="border_on_rb">person4</td><td nowrap class="border_on_rb"></td><td nowrap class="border_on_rb">Bluth, Maeby</td><td nowrap class="border_on_rb"><a href=mailto:bloblaw@theplanet.com>bloblaw@theplanet.com</a></td><td nowrap class="border_on_rb">555.555.5555</td><td nowrap class="border_on_rb">1337</td></tr>
EOL;

libxml_use_internal_errors(true);
$dom = DOMDocument::loadHTML($html);

$tds = $dom->getElementsByTagName('td');
foreach ($tds as $td) {
    echo $td->nodeValue.'<br>';
}

?>

花一些时间阅读有关 DOM 的手册/一些教程/文章/..,您将永远不会遇到 (RegEx) 解析(不仅仅是)HTML 的问题..

【讨论】:

  • 我最初想使用正则表达式的原因是因为我只需要从页面中提取一个匹配的 HTML 组,而且它似乎更有效地利用我的时间来酿造一个正则表达式字符串而不是编写一个完整的 DOM 解析器,而且我什至不确定这是否可行,因为我正在解析的 HTML very 格式很差,但据说 DOMDocument 甚至适用于格式错误的 HTML 文档,我不知道……但无论如何,正则表达式实在是太痛苦了,所以我正式放弃了它。
【解决方案3】:

重写它比调试它更容易,所以这是我的方法:

preg_match_all(
    '%<tr>[^<]*
      <td[^>]*><a.*?employee_id=(\d*).*?>(\w*)\s*.*?&nbsp;</td>[^<]*
      <td[^>]*>(\w*),\s*(\w*).*?&nbsp;</td>[^<]*
      <td[^>]*>(\w*).*?&nbsp;</td>[^<]*
      <td[^>]*>(\w*).*?&nbsp;</td>[^<]*
      <td[^>]*>(\w*).*?&nbsp;</td>[^<]*
      <td[^>]*>(\w*).*?&nbsp;</td>[^<]*
      <td[^>]*>(\w*).*?&nbsp;</td>[^<]*
      <td[^>]*><a[^>]*>(.*?)</a>.*?&nbsp;</td>[^<]*
      <td[^>]*>(\d{3}\.\d{3}\.\d{4}).*?&nbsp;</td>[^<]*
      <td[^>]*>(\w*).*?&nbsp;</td>[^<]*
    </tr>%sx', 
    $subject, $result, PREG_SET_ORDER);

它适用于您的示例,如果您喜欢或多或少的验证,您可以对其进行调整。

【讨论】:

  • 感谢您实际尝试回答我的问题,而不是告诉我我做错了。如果我没有成功重写它来解析整个 DOM 树(我怀疑我可能不会因为我必须解析的 HTML 质量差)我肯定会回到这个。
猜你喜欢
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-11
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 2018-01-11
相关资源
最近更新 更多