【问题标题】:Regex to find target="_blank" links and add text before closing </a> tag正则表达式查找 target="_blank" 链接并在关闭 </a> 标记之前添加文本
【发布时间】:2013-04-23 18:46:47
【问题描述】:

我需要能够解析一些文本并找到标签具有 target="_blank".... 的所有实例,并且对于每个匹配项,添加(例如):此链接在结束标记。

例如:

之前:

<a href="http://any-website-on-the-internet-or-local-path" target="_blank">Go here now</a>

之后:

<a href="http://any-website-on-the-internet-or-local-path" target="_blank">Go here now<span>(This link opens in a new window)</span></a>

这是一个 PHP 站点,所以我假设 preg_replace() 将是方法...我只是没有正确编写正则表达式的技能。

提前感谢任何人提供的任何帮助。

【问题讨论】:

  • 您可以使用问题标签下方的edit 链接来编辑您的问题和标题。

标签: php regex hyperlink


【解决方案1】:

您不应该使用正则表达式来解析 HTML,除非在定义非常明确和受控的情况下。

请尝试使用内置解析器:

$dom = new DOMDocument();
$dom->loadHTML($your_html_source);
$xpath = new DOMXPath($dom);
$links = $xpath->query("//a[@target='_blank']");
foreach($links as $link) {
    $link->appendChild($dom->createTextNode(" (This link opens in a new window)"));
}
$output = $dom->saveHTML();

或者,如果这是输出到浏览器,你可以只使用 CSS:

a[target='_blank']:after {
    content: ' (This link opens in a new window)';
}

【讨论】:

  • 哎哟!我正在从最深的地狱中研究一个巨大的该死的正则表达式。
【解决方案2】:

这将适用于锚标记替换......

$string = str_replace('<a ','<a target="_blank" ',$string);

【讨论】:

    【解决方案3】:

    @Kolink 是对的,但这是我的 RegExp 版本。

    $string = '<p>mess</p><a href="http://google.com.br/" target="blank" class=\"bother\">Google</a><p>mess</p>';
    echo preg_replace("/(\<a.*?target=\"blank\".*?>)(.*?)(\<\/a\>)/miU","$1$2(This link opens in a new window)$3",$string);
    

    【讨论】:

      【解决方案4】:

      这样就可以了:

      $newText = '<span>(This link opens in a new window)</span>';
      $pattern = '~<a\s[^>]*?\btarget\s*=(?:\s*([\'"])_blank\1|_blank\b)[^>]*>[^<]*(?:<(?!/a>)[^<]*)*\K~i';
      echo preg_replace($pattern, $newText, $html);
      

      然而,这种直接的字符串方法可能会替换 css 或 javascript 代码中的注释 html 部分、字符串或 cmets,并最终替换为 javascript 文字正则表达式,这充其量是不需要的,最坏的情况是根本不需要。这就是为什么如果你想避免这些陷阱,你应该使用 DOM 方法。您所要做的就是为每个链接附加一个具有所需属性的新节点:

      $dom = new DOMDocument;
      libxml_use_internal_errors(true);
      $dom->loadHTML($html);
      $xp = new DOMXPath($dom);
      $nodeList = $xp->query('//a[@target="_blank"]');
      
      foreach($nodeList as $node) {
          $newNode = dom->createElement('span', '(This link opens in a new window)');
          $node->appendChild($newNode);
      }
      
      $html = $dom->saveHTML();
      

      最后,最后一个选择是完全不更改 html 并使用 css:

      a[target="_blank"]::after {
          content: " (This link opens in a new window)";
          font-style: italic;
          color: red;
      }
      

      【讨论】:

        【解决方案5】:

        您将无法编写将评估无限长字符串的正则表达式。我建议:

        $h = explode('>', $html);
        

        这将使您有机会像任何其他数组一样遍历它,然后执行:

        foreach($h as $k){
            if(!preg_match('/^<a href=/', $k){
                continue;
                }elseif(!preg_match(/target="_blank")/, $k){
                continue;
                }else{
                $h[$k + 1] .= '(open in new window);
                }
            }
        $html = implode('>', $h);
        

        这就是我处理此类问题的方法。当然,我只是把它从我的脑海中抛开,并保证按原样工作,但对你的确切逻辑进行一些可能的调整,你就会得到你需要的东西。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-02-17
          • 1970-01-01
          • 2015-08-19
          • 1970-01-01
          • 1970-01-01
          • 2011-09-20
          • 1970-01-01
          相关资源
          最近更新 更多