【问题标题】:Regex to match URLs in a text which are not part of an html tag [duplicate]正则表达式匹配文本中不属于 html 标记的 URL [重复]
【发布时间】:2020-05-02 08:10:56
【问题描述】:

我正在使用以下正则表达式将纯 URL 替换为文本中的 html 链接:

preg_replace('/(http[s]{0,1}\:\/\/\S{4,})\s{0,}/ims', '<a href="$1" target="_blank">$1</a> ', $text_msg);

现在我想修改正则表达式,它仅在 URL 后面没有双引号时才替换 URL,因此它不是标签的一部分(即 url 在字符串的开头,开始一行或一个空格之后)。

例子:

  • 这是链接&lt;a href="http://test.com"&gt; ...(URL不应被替换)

  • http://test.com(在一行的开头或整个多行字符串应该被替换)

  • 这是网站:http://test.com(应替换 URL)

谢谢。

【问题讨论】:

  • 也添加输入和您的预期输出。
  • 另外,不要提供不相关的代码。有问题的代码与您当前的问题无关。您只是向我们展示了解决您之前遇到的问题的代码。而是向我们展示您尝试解决当前问题的代码,并告诉我们为什么没有按照您的意愿去做。
  • 为简化起见,您的实际问题是将文本与 HTML 分开,而不是解析 URL(您已经了解了该部分)。做前者,只需使用类似DOMDocument 的东西,它是一个 HTML 解析器,能够从 DOM 中提取文本节点,然后在该文本上运行您的正则表达式。
  • @sherif 你提出的问题很相似,但没有回答我的问题。当且仅当 URL 后面没有双引号时,我才需要替换。代码是相关的,因为我希望它被更改。
  • 不,只有在 URL 后面没有双引号时,您才不想替换它。您想要的是将 DOM 内的纯文本 URL 替换为 HTML。有关详细信息,请参阅下面的答案。

标签: php regex preg-replace


【解决方案1】:

您的问题实际上分解为两个较小的问题。您已经解决了其中一个问题,即使用正则表达式解析 URL。第二部分是从 HTML 中提取文本,这根本不是用正则表达式就能轻松解决的。您的困惑是试图同时使用正则表达式(解析 HTML 和解析 URL)。请参阅parsing HTML with regex SO Answer,了解有关为什么这是一个坏主意的更多详细信息。

因此,我们只需要使用 HTML 解析器(如 DOMDocument)从 HTML 中提取文本节点并解析这些文本节点内的 URL。

这是一个例子

<?php
$html = <<<'HTML'
    <p>This is a URL http://abcd/ims in text</p>
HTML;

$dom = new DOMDocument;
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

// Let's walk the entire DOM tree looking for text nodes
function walk(DOMNode $node, $skipParent = false) {
    if (!$skipParent) {
        yield $node;
    }
    if ($node->hasChildNodes()) {
        foreach ($node->childNodes as $n) {
            yield from walk($n);
        }
    }
}

foreach (walk($dom->firstChild) as $node) {
    if ($node instanceof DOMText) {
        // lets find any links and change them to HTML
        if (preg_match('/(http[s]{0,1}\:\/\/\S{4,})\s{0,}/ims', $node->nodeValue, $match)) {

            $node->nodeValue = preg_replace('/(http[s]{0,1}\:\/\/\S{4,})\s{0,}/ims', "\xff ",
                                            $node->nodeValue);
            $nodeSplit = explode("\xff", $node->nodeValue, 2);
            $node->nodeValue = $nodeSplit[1];
            $newNode = $dom->createTextNode($nodeSplit[0]);
            $href = $dom->createElement('a', $match[1]);
            $href->setAttribute('href', $match[1]);
            $node->parentNode->insertBefore($newNode, $node);
            $node->parentNode->insertBefore($href, $node);
        }
    }
}

echo $dom->saveHTML();

这会为您提供所需的 HTML 作为输出:

这是一个 URL http://abcd/ims 文本

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-28
    • 2017-10-04
    • 2019-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2012-04-02
    相关资源
    最近更新 更多