Необязательная группа Perl в произвольном месте - PullRequest
1 голос
/ 11 апреля 2019

Мне нужно захватить несколько групп, и некоторые из них являются необязательными. Я читал о факультативных в https://www.regular -expressions.info / option.html , но ? не работает для меня. Файл примера:

Code>1<Code
foo
Prod>2<Prod
foo
Type>3<Type

perl -0777ne 'print qq($1;$2;$3) if /Code>(.*?)<Code.*?Prod>(.*?)<Prod.*?Type>(.*?)<Type/s' < tst.txt дает 1;2;3, как и ожидалось.

Теперь я хочу добавить опциональность ко второй группе, например perl -0777ne 'print qq($1;$2;$3) if /Code>(.*?)<Code.*?(Prod>(.*?)<Prod)?.*?Type>(.*?)<Type/s' < tst.txt, но она перестает печатать вторую группу, давая 1;; (из-за вложенного 3-го пустого, такого же, как 2-й, $ 4 печатает 3).

За Необязательное групповое выражение Я пробовал perl -0777ne 'print qq($1;$2;$3;$4) if /Code>(.*?)<Code.*?(Prod>(.*?)<Prod|.*?).*?Type>(.*?)<Type/s' < tst.txt, но снова получил 1;;;3.

Можно ли извлекать произвольно в любом месте, как я могу иметь другие вещи между группами и как?

EDIT: удаление одного ? perl -0777ne 'print qq($1;$2;$3;$4) if /Code>(.*?)<Code.*?(Prod>(.*?)<Prod|.*).*?Type>(.*?)<Type/s' < tst.txt дает
1; foo Prod>2<Prod foo ;;3 поэтому захватывает все между 1-м и 3-м (похоже, что 2-й вариант извлечен, а не один до |), а не только 2-й.

EDIT: реализовано предложение ?:, теперь perl -0777ne 'print qq($1;$2;$3;$4) if /Code>(.*?)<Code.*?(?:Prod>(.*?)<Prod|.*).*?Type>(.*?)<Type/s' < tst.txt дает 1;;3;

1 Ответ

3 голосов
/ 11 апреля 2019

Вы ищете (?:...) - префикс ?: внутри группы захвата делает его просто группой, а не захваченным.Я рекомендую использовать это каждый раз, когда есть группа, которая не захвачена, чтобы прояснить ваши намерения.Это говорит: «Я группирую это, но не сохраняю это».Это может даже ускорить выполнение, но это не главное преимущество.

Пример:

perl -0777nE 'say qq[$1;$2;$3] if /Code\>(.*?)\<Code.*?(?:Prod\>(.*?)\<Prod.*?)?Type\>(.*?)\<Type/s' < t

Это распечатывает 1;2;3

Однако я бы также предложилПосмотрите на синтаксис (?<name>...), где вы можете назвать свои группы и использовать %+ (например, $+{name}) для извлечения полей по имени, а не по позиции.По моему опыту, это делает и регулярное выражение, и код, основанный на нем, более читабельным.

...