Полезное эмпирическое правило, приписываемое Рэндалу Шварцу, заключается в использовании split
, когда вы знаете, что вы хотите отбросить, или m//
и захвате скобок, когда вы знаете, что ты хочешь сохранить. Однако применить его к вашему вопросу немного сложно, потому что вы хотите сделать и то, и другое. То есть либо
- выбросить завершающую запятую или
- сохранить правую скобку
Программа ниже использует m//
и захват, поэтому она определяет проблему с точки зрения того, что она хочет сохранить . Конечно, )
на конце очень просто. Чтобы исключить запятую из буфера захвата, код использует положительное упреждающее утверждение : захват должен останавливаться на символе всего за до запятой.
Возможность, которую легко упустить, это имя, которое также должно заканчиваться в конце строки. Скажем, Стэн Ли был фамилией, а не второй Без альтернативы $
Стэн был бы опущен.
Код использует DEFINE
и именованные подшаблоны, чтобы помочь читателю понять регулярное выражение. Недостатком этого подхода является то, что он генерирует дополнительные буферы захвата, поэтому вы должны использовать цикл вместо @names = /$name_pattern/g
.
Как написано, он принимает немного больший язык, чем тот, который вы указали в своем вопросе, , а именно , он разрешает и отбрасывает запятую между двумя актерами, у обоих из которых также есть имена персонажей.
#! /usr/bin/env perl
use warnings;
use strict;
*ARGV = *DATA; # for demo only
my $name_pattern = qr/
( # capture into $1
(?&name) (?: (?&comma_terminated) | \) | $ )
)
# discard trailing whitespace and optional comma
(?: \s* (?: , \s*)? )
(?(DEFINE)
(?<name> .+? )
(?<comma_terminated> (?= ,) )
)
/x;
while (<>) {
my @names;
push @names, $1 while /$name_pattern/gx;
print "[$_]\n" for @names;
}
__DATA__
Jon Favreau, Stan Lee, Justin Theroux, Robert Downey Jr. (Tony Stark) Gwyneth Paltrow (Pepper Potts) Don Cheadle (James Rhodes) foo
Выход:
[Jon Favreau]
[Stan Lee]
[Justin Theroux]
[Robert Downey Jr. (Tony Stark)]
[Gwyneth Paltrow (Pepper Potts)]
[Don Cheadle (James Rhodes)]
[foo]