Исходя из вашего примера кода и текста, я не совсем уверен, как выглядят ваши исходные данные, поэтому я не могу предоставить гораздо более подробную информацию. Тем не менее, исходя из того, как сопоставлять символы из более ранней части сопоставления, самый простой способ сделать это с сопоставлением массивов:
my $input = "(abc)aaaaaa(def)ddee(ghi)gihgih(jkl)mnmnoo";
my @output = $input ~~ m:g/
:my @valid; # initialize variable in regex scope
'(' ~ ')' $<valid>=(.*?) # capture initial text
{ @valid = $<valid>.comb } # split the text into characters
$<text>=(@valid+) # capture text, so long as it contains the characters
/;
say @output;
.say for @output.map(*<text>.Str);
Выходные данные которого
[「(abc)aaaaaa」
valid => 「abc」
text => 「aaaaaa」 「(def)ddee」
valid => 「def」
text => 「ddee」 「(ghi)gihgih」
valid => 「ghi」
text => 「gihgih」]
aaaaaa
ddee
gihgih
В качестве альтернативы, вы можете сохранить все определение класса символов в переменной и ссылаться на переменную как <$marker-char-class>
, или, если вы хотите избежать этого, вы можете определить все это встроенным как код, который будет интерпретироваться как регулярное выражение с <{ '<[' ~ $marker ~ ']>' }>
. Обратите внимание, что оба метода связаны с одной и той же проблемой: вы создаете класс символов из синтаксиса регулярного выражения, для которого могут потребоваться escape-символы или определенный порядок, и поэтому он определенно неоптимален.
Если это то, что вы будете делать очень часто и не очень быстро, вы также можете определить свой собственный токен метода регулярных выражений, но это, вероятно, очень излишне и лучше подойдет как отдельный вопрос.