0

我在尝试编写非贪婪的正则表达式语句时遇到了麻烦。

这是我的字符串:

<strong>name</strong><strong>address</strong>mailto:blabla@email.com

这是我的正则表达式查询:

<strong>(.*?)</strong>.*?([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})

问题是我需要地址,而不是字符串中的名称。所以我需要正则表达式查询是非贪婪的,并且采用最近的<strong></strong>而不是最远的。

在我的搜索字符串中也有多个实例,所以它必须一次匹配多个实例,而不是仅仅.*在它前面添加一个(贪婪的)东西。

所以它必须匹配这个的所有实例,并提取地址,而不是名称:

   <strong>name</strong><strong>address1</strong>mailto:blabla@email.com
   <strong>name</strong><strong>address2</strong>mailto:blabla@email.com
   <strong>name</strong><strong>address3</strong>mailto:blabla@email.com
   <strong>name</strong><strong>address4</strong>mailto:blabla@email.com

提前致谢!

4

3 回答 3

2

首先,正则表达式是匹配 HTML 的次优工具(这是一个很好的例子)。如果您知道如何使用解析器,您会对解析器更满意(也许其中一位 PHP 大师可以推荐一个)。

话虽如此,使用正则表达式的更好方法可能是<strong>明确匹配(并丢弃)第一个标签:

<strong>.*?</strong><strong>(.*?)</strong>.*?([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})

这绝不是一个好的、可靠的、防弹的解决方案,但至少它适用于您的示例数据。

或者,如果您可以更具体地了解相关标签之间/之后允许的内容,那么如何:

<strong>([^<>]*)</strong>(?:mailto:)?([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})
于 2011-03-21T20:00:59.227 回答
0

查看您的测试数据,我推断出以下规则:如果...

  1. 姓名和地址都包含在 STRONG 元素中,电子邮件紧随其后,并且
  2. STRONG 元素的属性、名称和地址都没有尖括号,并且
  3. 电子邮件地址部分始终以mailto:, 和
  4. 两个 STRONG 元素中没有其他 HTML 元素,

那么这个经过测试的代码应该可以解决问题:

$re = '%
    # Capture name and address in <strong> element then email.
    <strong[^>]*>\s*([^<>]+)</strong\s*>\s*  # $1: Name.
    <strong[^>]*>\s*([^<>]+)</strong\s*>\s*  # $2: Address.
    (mailto:\S+)                             # $3: Email.
    %ix';
$count = preg_match_all($re, $text, $matches);
if ($count) {
    printf("%d matches found:\n", $count);
    print_r($matches);
    for ($i = 0; $i < $count; ++$i) {
        printf("Match %d: Name: \"%s\", Address: \"%s\", Email: \"%s\":\n",
            $i + 1, $matches[1][$i], $matches[2][$i], $matches[3][$i]);
    }
} else {
    printf("No matches found.\n");
}
于 2011-03-21T21:28:22.267 回答
0

不要使用正则表达式来解析 HTML。

http://htmlparsing.com/php.html

于 2011-03-21T20:56:15.780 回答