用于转换mailto链接的正则表达式

时间:2013-04-29 21:57:16

标签: php regex

我一直在使用这个普通快递(可能在几年前的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表达式正在寻找“&lt;”得到件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 个答案:

答案 0 :(得分:1)

你可以直接替换&lt; a&gt;之间的整个匹配。标记为.*?。将([^<|@]*)(@?)([^<]*)替换为(.*?),它将包含&lt; a&gt;内的所有内容。标签包括嵌套标签。您可以使用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

答案 1 :(得分: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'];

答案 2 :(得分:0)

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

[^>]*>([^>]+)@.* 你需要的应该是结果的第一组。

答案 3 :(得分:0)

试试这个正则表达式

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

/^/ - 字符串开头

/(<.*>)/ - 第一个匹配组,以&lt;开头然后介于两者之间,直到它击中&gt;

/(.*)(@)/ - 匹配括号内的任何内容