【问题标题】:regex negative with negative match for part of string正则表达式否定与部分字符串的否定匹配
【发布时间】:2014-08-04 13:59:50
【问题描述】:

我已经尝试了几个版本,用于负前瞻或负后瞻,在 SO 和整个网络上都可以找到,但我就是无法让它工作。

我想从大量文本中提取 html 链接,除非它们是用图像锚定的。 例子:

<a href="somelink">sometext</a>  <-- match and grab somelink
<a href="anotherlink"><img src="someimage"></a>  <-- ignore link

我试过了

preg_match_all('/<a href="(.*?).*?>.*?<\/a>^((?!<img).)*/', $string), $matches);
preg_match_all('/<a href="(.*?).*?>.*?<\/a>(?<!img )/', $string, $matches);

和其他类似的版本

【问题讨论】:

  • 也许可以试试这个:&lt;a href="(.*?)"&gt;[^(?:&lt;img)] 不幸的是,这只有在img 标签紧跟在href 标签之后才有效。你可以测试它here。虽然您可能应该测试您的实际文本
  • 我不介意它是否仅适用于 href 之后的 img 标签。我使用了您的示例并对其进行了修改,以允许链接标记中的文本多于 href 属性。结果数组中的结果如下;它在第一个图像标记之前抓取链接,但结果中排除了以下正确链接。所以对我来说它没有用。

标签: php regex preg-match-all


【解决方案1】:

我们不要为此使用正则表达式。解析 HTML,获取所有锚标签并检查它们是否包含 &lt;img&gt; 元素。

<?php
$html = '<a href="somelink">sometext</a><a href="anotherlink"><img src="someimage"></a>';

$doc = new DOMDocument();
$doc->loadHTML($html);

$anchors = $doc->getElementsByTagName('a');
foreach ($anchors as $a) {
    if ($a->getElementsByTagName('img')->length === 0)
        echo $doc->saveHTML($a);
}

是的,它更长,但它的可读性和自我记录性也好得多。

输出:

<a href="somelink">sometext</a>

【讨论】:

  • 如果可能的话,我想用正则表达式来解决这个问题。它可以让我快速过滤掉没有以特定方式格式化的链接。
  • @Borje 可能可以编写一个“足够好”以满足您的需求的正则表达式,但这可以完成工作并且更加灵活。如果你使用正则表达式,几乎总会有一个边缘情况让你失望。也许这种方法可以适应您的要求。我建议您编辑您的问题,使其更具体。
  • 感谢您抽出宝贵时间来帮助我,但我真的不能比我更具体。我需要从文本中获取链接。我想用正则表达式来做。从结果中我想排除与图像一起显示的链接。这是我遇到问题的排除部分。如果我想通过检查元素的结构或前面的文本来过滤链接,我可以自己修改我的正则表达式来处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-19
  • 2011-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-29
相关资源
最近更新 更多