正则表达式和php问题,需要非贪婪的搜索!

时间:2011-03-21 19:55:00

标签: php regex regex-greedy

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

这是我的字符串:

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

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

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

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

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

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

   <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

提前致谢!

3 个答案:

答案 0 :(得分: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})

答案 1 :(得分:0)

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

请参阅http://htmlparsing.com/php.html

答案 2 :(得分:0)

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

  1. 名称和地址都包含在STRONG元素中,电子邮件紧接着,AND
  2. STRONG元素的属性,名称和地址都没有尖括号,AND
  3. 电子邮件地址组件始终以mailto:,AND
  4. 开头
  5. 两个STRONG元素中没有其他HTML元素,
  6. 然后这个经过测试的代码可以解决这个问题:

    $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");
    }