Вот подход, использующий split , который в этом случае также нуждается в тщательном регулярном выражении
use warnings;
use strict;
use feature 'say';
my $string = # broken into two parts for readabililty
q(mail1, local<mail1@mail.local>, mail2@mail.local, )
. q(<mail3@mail.local>, mail4, local<mail4@mail.local>);
my @addresses = split /@.+?\K,\s*/, $string;
say for @addresses;
split
принимает полное регулярное выражение в своей спецификации разделителя.В этом случае я полагаю, что каждая запись отделяется запятой, которая идет после адреса электронной почты, поэтому @.+?,
Соответствие шаблону только тогда, когда ему предшествует другой, напоминает негативный взгляд сзади до запятой.Но они не могут быть переменной длины, как раз здесь.
Вместо этого мы обычно можем сопоставить шаблон @.+?
, а затем использовать \K
форму (вид сзади), которая отбрасывает все предыдущие совпадения, чтобы они не были взяты из строки,Таким образом, вышеприведенный код разделяется на ,\s*
, когда этому предшествует адрес электронной почты @...
(что не используется).
Он печатает
mail1, local<mail1@mail.local>
mail2@mail.local
<mail3@mail.local>
mail4, local<mail4@mail.local>
Правкаспрашивает о цитировании описания, предшествующего <...>
, когда оно там.Простой способ - сделать еще один проход, как только адреса были проанализированы из строки, как указано выше.Например,
my @addresses = split /@.+?\K,\s*/, $string; #/ stop syntax highlight
s/(.+?,\s*.+?)</"$1"</ for @addresses;
say for @addresses;
Регулярное выражение в цикле - это один из способов изменить элементы массива.Я использую его для его эффективности (изменения элементов на месте), краткости и в качестве демонстрации следующих свойств.
В цикле foreach переменная индекса (или $_
) является псевдонимом для обрабатываемого в данный момент элемента , поэтому при его изменении изменяется этот элемент.Это известный источник ошибок, когда допускается неосознанно, что было еще одной причиной показать его в приведенной выше форме.
В операторе также используется модификатор оператора , и он эквивалентен
foreach my $elem (@addresses) {
$elem =~ s/(.+?,\s*.+?)</"$1"</;
}
Этот способ часто считается более правильным, но я обнаружил, что другая форма более четко подчеркивает, что элементы меняются, когда это является единственной целью foreach
.