PHP regex для получения всех адресов электронной почты, которые являются значениями атрибутов HTML-элемента, например " - PullRequest
0 голосов
/ 16 февраля 2019

У меня есть этот шаблон регулярных выражений /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i, который я использую для получения адресов электронной почты из строки.Но теперь я хотел бы получить только все адреса электронной почты, которые являются значением произвольного атрибута HTML-элемента, включая сам атрибут.Посмотрите на мой пример, и все должно быть ясно:

<?php
$subject = 'abc dont@get.me 123 <input value="please@get.me">xyz';
$pattern = '/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i';
preg_match_all( $pattern, $subject, $matches );
var_dump( $matches );

выдаст что-то вроде:

array(1) { [0]=> array(2) {
    [0]=> string(11) "dont@get.me"
    [1]=> string(13) "please@get.me"
} }

, но мне нужно:

array(1) { [0]=> array(1) {
    [0]=> string(13) "value="please@get.me""
} }

Пожалуйста,знать, что <input value="please@get.me"> это просто пример.Мне нужен шаблон, который может обрабатывать «все» HTML-элементы с атрибутами «все» (я поместил «все» в кавычки, чтобы прояснить, что я знаю, что могут быть некоторые крайние случаи, когда шаблон может потерпеть неудачу, потому что HTML нерегулярный) и:

<?php
$subject = "<br data-xyz=please@get.me /> dont@get.me <[tag] [attr]='[pre] andPlease@get.me [ap]'>";
preg_match_all( $pattern, $subject, $matches );
var_dump( $matches );

должен выдавать что-то вроде:

array(1) { [0]=> array(2) {
    [0]=> string(13) "data-xyz=please@get.me"
    [1]=> string(13) "[attr]='[pre] andPlease@get.me [ap]'"
} }

Если честно, я действительно плохо разбираюсь в шаблонах регулярных выражений, поэтому не имею понятия о том, как этого добитьсяЭто.Надеюсь, что кто-нибудь может помочь мне с этим!


РЕДАКТИРОВАТЬ: другое решение, чем регулярное выражение также было бы хорошо!

Ответы [ 2 ]

0 голосов
/ 16 февраля 2019

Чтобы использовать для этого DOMDocument и XPath, вам необходимо сначала загрузить документ в формате HTML, а затем использовать XPath для поиска любых атрибутов, содержащих символ «@» ....

$subject = 'abc dont@get.me 123 <input value="please@get.me">
          <span t="please@get.me2" u="please@get.me3" />
           <span t="pleasedont get.me" />
        <span t="@@@@">xyz';

$doc = new DOMDocument();
$doc->loadHTML($subject);

$xp = new DOMXPath($doc);
$possibilities = $xp->query('//*/@*[contains(., "@")]');

foreach ( $possibilities as $match )    {
    if ( filter_var($match->nodeValue, FILTER_VALIDATE_EMAIL) ) {
        echo $match->parentNode->nodeName." ".
            $match->nodeName."=". $match->nodeValue.PHP_EOL;
    }
}

( Редактировать в соответствии с предложением Хайдена в комментарии - я обновил ответ, чтобы проверить, что это адрес электронной почты, прежде чем выводить значения).

выведет

input value=please@get.me
span t=please@get.me2
span u=please@get.me3

, чтобы сломать XPath ...

//*/@*[contains(., "@")]

//* ищет любой узел - /@* означает любой атрибут - выражение [] после того, как это условие,поэтому будут возвращены только те узлы, которые соответствуют условию.Условие contains(., "@") говорит о том, что текст узла должен содержать @.Таким образом, вместе он говорит, что любой узел с атрибутом, который содержит @.$match->nodeValue затем выведет значение, а $match->nodeName отобразит имя атрибута, только что добавленное $match->parentNode->nodeName также отобразит имя элемента.

Также обратите внимание, что этот метод будет возвращать несколько совпадений с одного и того жеэлемент, но в другом атрибуте (например, please@get.me3).

0 голосов
/ 16 февраля 2019

Вы можете использовать это регулярное выражение, чтобы обеспечить сопоставление любого имени тега, которое будет содержать электронную почту, если любое имя значения атрибута содержит слово \w,

<\w+.*?([\w-]+=["']*\s*(?:\w+\s*)*[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\s*(?:['"]?(?:\w+\s*)*['"]?)?["']*).*?>

И захватывать значение первого шаблона группировки.

Здесь предполагается, что имя тега и имя атрибута будут содержать символы из \w, но если вы хотите добавить дополнительные символы, такие как включение - или ., вам нужно будет изменить \wв [\w.-] в регулярном выражении.

Демо

Редактировать:

Другой способ, есливы не хотите захватывать данные из группы 1 и вместо этого хотите, чтобы полное совпадение содержало только имя атрибута и адрес электронной почты, вы можете использовать оператор \K с этим регулярным выражением,

<\w+.*?\K[\w-]+=["']*\s*(?:\w+\s*)*[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\s*(?:['"]?(?:\w+\s*)*['"]?)?["']*(?=.*?>)

Демо сполное совпадение, содержащее нужный вам текст

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...