Regex и PHP вопрос, нужен не жадный поиск! - PullRequest
0 голосов
/ 21 марта 2011

У меня проблемы с попыткой написать не жадное выражение регулярного выражения.

Вот моя строка:

<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

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 21 марта 2011

Во-первых, регулярные выражения являются неоптимальным инструментом для сопоставления 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})
0 голосов
/ 22 марта 2011

Глядя на ваши тестовые данные, вот правила, которые я выводю: Если ...

  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");
}
0 голосов
/ 21 марта 2011

Не используйте регулярные выражения для разбора HTML.

См. http://htmlparsing.com/php.html

...