0

我一直在使用这个正则表达式(几年前可能在 stackoverflow 上找到)在 PHP 中转换 mailto 标签:

preg_match_all("/<a([ ]+)href=([\"']*)mailto:(([[:alnum:]._\-]+)@([[:alnum:]._\-]+\.[[:alnum:]._\-]+))([\"']*)([[:space:][:alnum:]=\"_]*)>([^<|@]*)(@?)([^<]*)<\/a>/i",$content,$matches);

我通过它$content = '<a href="mailto:name@domain.com">somename@domain.com</a>'

它返回这些匹配的部分:

0 <a href="mailto:name@domain.com">somename@domain.com</a>
1  
2 "
3 name@domain.com
4 name
5 domain.com
6 "
7 
8 somename
9 @
10 domain.com

示例用法:<a href="send.php?user=$matches[4][0]&dom=$matches[5][0]">ucwords($matches[8][0])</a>

我的问题是,一些链接包含嵌套标签。由于 preg 表达式正在寻找“<”来获取 8、9、10 块,并且嵌套标签将其丢弃......

例子: <a href="mailto:name@domain.com"><span><b>somename@domain.com</b></span></a>

我需要忽略嵌套标签,只提取“某些名称”部分:

match part 8 = <span><b>
match part 9 = somename
match part 10 = @
match part 11 = domain.com
match part 12 = </b></span>

我试图通过调整让它工作,([^<|@]*)(@?)([^<]*)但我无法找出正确的语法来匹配或忽略嵌套标签。

4

4 回答 4

1

您可以将 <a> 标记之间的整个匹配替换为 a .*?。替换([^<|@]*)(@?)([^<]*)(.*?),它将包含 <a> 标记中的所有内容,包括嵌套标记。之后,您可以使用 striptags 或其他正则表达式删除嵌套标签。

但是,正则表达式不太擅长 html 嵌套标签。你最好使用 DOMDocument 之类的东西,它专门用于解析 html。就像是:

<?php
$DOM = new DOMDocument();
$DOM->loadXML('<a href="mailto:name@domain.com"><span><b>somename@domain.com</b></span></a>');

$list = $DOM->getElementsByTagName('a');

foreach($list as $link){
    $href = $link->getAttribute('href');
    $text = $link->nodeValue;
    //only match if href starts with mailto:
    if(stripos($href, 'mailto:') === 0){
        var_dump($href);
        var_dump($text);
    }
}

http://codepad.viper-7.com/SqDKgr

于 2013-04-29T22:19:55.780 回答
0

Try this regex

/^(<.*>)(.*)(@)/

/^/- Start of string

/(<.*>)/ - First match group, starts with < then anything in between until it hits >

/(.*)(@)/ - Match anything up to the parenthesis

于 2013-04-29T22:44:38.387 回答
0

你可以试试这个模式:

$pattern = '~\bhref\s*+=\s*+(["\'])mailto:\K(?<mail>(?<name>[^@]++)@(?<domain>.*?))\1[^>]*+>(?:\s*+</?(?!a\b)[^>]*+>\s*+)*+(?<content>[^<]++)~i';
preg_match_all($pattern, $html, $matches, PREG_SET_ORDER);
echo '<pre>' . print_r($matches, true) . '</pre>';

你可以像这样访问你的数据:

echo $matches[0]['name'];
于 2013-04-29T22:13:15.587 回答
0

要仅访问链接中的部分,请尝试

[^>]*>([^>]+)@.* 您需要的应​​该在结果的第一组中。

于 2013-04-29T22:17:21.120 回答