Вам следует напомнить себе об основных аспектах регулярных выражений: по умолчанию они жадные, если может совпадать все выражение.
Ваш пример
/.*(,X\{(.*?)\})?.*(,Y\{(.*?)\})?/
имеет тольконеобязательные элементы, поэтому он всегда будет совпадать - пустая строка, если ничего больше.
Проблема в том, что RE будет жадным в самой ранней возможной позиции и в максимально возможной степени (хотя все еще будет в состоянии соответствовать остальнымвыражение).Поэтому первый .*
будет потреблять все в вашей строке, оставляя другие подвыражения по умолчанию равными пустым строкам (через ?
или *
).
Трудно сделать X {} и Y{} необязательно, но предпочитая их присутствие;Если вы сделаете их необязательными, механизм регулярных выражений никогда не будет использовать их, если с этим не справится.
Я бы предложил использовать подвыражения с чередующимися комбинациями X {} и Y {}, присутствующими либо внутри (?:...|...)
(с последующим присвоением значений переменным в зависимости от используемой ветви) или внутри сброса ветви (?|...|...)
(записывается как правильный код для использования /x
):
use strict;
use warnings;
foreach my $data (<DATA>) {
chomp $data;
if ($data =~ /
(?|
.*? # both X and Y present
,X \{ ([^{}]*) \}
.*?
,Y \{ ([^{}]*) \}
|
.*? # only X present
,X \{ ([^{}]*) \}
.*
()
|
.*? # only Y present
()
,Y \{ ([^{}]*) \}
|
() () # neither X nor Y present
)
/x) {
print "$1, $2\n";
}
}
exit 0;
__DATA__
example ,X{whateverX},...,Y{whateverY} the end
example2 ,X{whateverX2},random data to the end
example3 with data before ,Y{whateverY3} the end
example4 with just data and no separators
Будет выводить:
whateverX, whateverY
whateverX2,
, whateverY3
,
Обратите внимание, что необходимы ведущие .*?
, иначе ()()
будет совпадать в каждом случае.