【问题标题】:How to strip all anchor tags and href attribute only?如何仅剥离所有锚标签和 href 属性?
【发布时间】:2014-04-17 22:04:27
【问题描述】:

我有一个场景,我需要从 HTML 内容中去除所有锚点,但这样做时我不想去除锚点标签的 href 部分。

目前我正在使用这个正则表达式来使用 preg_replace() 剥离锚。

<a [^>]*> strips all the anchor tag
<a.+href\=[\"|\'](.+)[\"|\'].*\>.*\<\/a\> - matches href

示例字符串: "anchor href="mailto:xyz@gmail.com">namemail 锚点"

在执行 preg_replace() 之后,我应该得到“mailto:xyz@gmail.com”字符串,因为其余的文本都应该被剥离。

【问题讨论】:

  • This 可能会有所帮助。
  • 您无法使用正则表达式成功/可靠地实现此目的。

标签: php html regex anchor


【解决方案1】:
$html = '<a href="http://www..." x=asdasda?></a>';
$html = preg_replace("|<a[^>]*href\s*=\s*([\"'])([^\"']*)\\1[^>]*>[^<]*</a>|si", "$2", $html);

输出:

http://www...

【讨论】:

  • 这不适用于$html = "&lt;a href='http://google.com/search?q=\"cheese\"'&gt;search for cheese&lt;/a&gt;";
  • 它对我有用 我从 html 格式的链接中得到了裸链接 &lt;a href="http://exmple.com/author/vistor/" title="some" relation="author" &gt;profile&lt;/a&gt; 结果是 http://exmple.com/author/vistor/
【解决方案2】:

使用 DOMDocument 解析 HTML 会比尝试使用正则表达式更成功:

以下是您可以应该做什么的概念验证:

function replaceAnchorTags($html) {
    //Intialise document using provided HTML
    $doc = new DOMDocument();
    @$doc->loadHTML($html);         //suppress invalid HTML warnings
    $doc_elem = $doc->documentElement;

    traverse($doc, $doc_elem);
    return $doc->saveHTML();
}

function traverse(&$doc, $elem) {
    if ($elem->nodeType === XML_ELEMENT_NODE and $elem->tagName == "a") {
        $href = $elem->getAttribute("href");
        // Obviously here you might want to keep the anchor's inner HTML as
        // well as the URL...
        $text_replacement = $doc->createTextNode($href);
        $elem->parentNode->replaceChild($text_replacement, $elem);
    }

    if ($elem->hasChildNodes()) {
        $children = $elem->childNodes;
        for ($i=0, $max=$children->length; $i<$max; $i++) {
            traverse($doc, $children->item($i));
        }
    }
}

$html = "<p>Hello <a href='http://twitter.com'>Brave New</a> World</p>";

echo replaceAnchorTags($html);

【讨论】:

    【解决方案3】:

    试试这个正则表达式:

    ~<a.+?href=(["'])(.+?)\1.*?>.*?</a>~is
    

    说明

    详细说明

    ~<a.+?href=(["'])(.+?)\1.*?>.*?</a>~is
    
    <a    # matches the characters <a literally (case sensitive)
    .+?   # matches any character, the least possible
    href= # matches the characters href= literally (case sensitive)
    1st Capturing group (["'])
        ["'] # matches a single character. Either " or '
    2nd Capturing group (.+?)
        .+?  # matches any character, the least possible
    \1    # matches a single character corresponding the character found in first capturing group.
    .*?   # matches zero or more characters, the least possible
    >     # matches the character > literally
    .*?   # matches zero or more characters, the least possible
    </a>  # matches the characters </a> literally (case sensitive)
    i modifier: ignore case
    s modifier: single line. Dot matches newline characters
    
    NOTA: The ~ between the regex delimit it and allow us to don't escape /.
    

    演示

    http://regex101.com/r/fX1fP1

    一些注意事项

    • [\"|\']

      不要过度逃避。仅当您想显式匹配元字符时才转义元字符。请改用["|']

    • ["|']

      除非你想匹配它,否则不要在字符类中使用|。字符类中的字符已经是ORed。检查以下描述:

      当您键入 ["|'] 时,正则表达式会看到:

      当您键入 ["'] 时,正则表达式会看到:

    【讨论】:

    • 我在 php $strText = 'Name<Nameemail>'中使用这个; $strText = preg_replace( '#.*?\ #is ', '', $strText ); 但它并没有保留 href 部分,而是剥离了整个锚标记。
    • @user2173474 您不需要转义第一个双引号、> 和 /。
    • 虽然这是一个很好的正则表达式和很好的解释,但它不会成功匹配/替换所有有效的 URL。特别是那些包含 '" 字符的 URL。要实现 OP 想要的,您不能使用正则表达式。您必须解析 HTML。
    • 这打破了锚点&lt;a href='http://google.com/search?q="cheese"'&gt;search for cheese&lt;/a&gt;,并且PHP中没有PCRE修饰符g,你需要使用preg_replace_all()来代替。
    • @Jon 感谢您的 cmets。我已经改进了关于这个问题的正则表达式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-19
    • 2014-03-16
    • 1970-01-01
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多