Raku tem uma notação regex recursiva interessante e emocionante: <~~>
.
Então no REPL, podemos fazer isso:
[0] > 'hellohelloworldworld' ~~ m/ helloworld /;
「helloworld」
[1] > 'hellohelloworldworld' ~~ m/ hello <~~>? world /;
「hellohelloworldworld」
Indo diretamente do Raku Docs para expressões regulares recursivas , podemos capturar/contar vários níveis de aninhamento:
~$ raku -pe '#acts like cat here' nest_test.txt
not nested
previous blank
nestA{1}
nestB{nestA{1}2}
nestC{nestB{nestA{1}2}3}
~$ raku -ne 'my $cnt = 0; say m:g/ \{ [ <( <-[{}]>* )> | <( <-[{}]>* <~~>*? <-[{}]>* )> ] \} {++$cnt} /, "\t $cnt -levels nested";' nest_test.txt
() 0 -levels nested
() 0 -levels nested
() 0 -levels nested
(「1」) 1 -levels nested
(「nestA{1}2」) 2 -levels nested
(「nestB{nestA{1}2}3」) 3 -levels nested
(Acima, altere say
para put
para retornar apenas a string capturada).
Mas recentemente me deparei com um problema ao tentar resolver uma questão sobre Unix e Linux , que é: como limitar a recursão? Digamos que queremos capturar apenas abaixo nestB
. Existe alguma maneira de fazer isso usando a <~~>
sintaxe regex recursiva?
~$ raku -ne 'my $cnt = 0; say m:g/ nestB \{ [ <( <-[{}]>* )> | <( <-[{}]>* <~~>*? <-[{}]>* )> ] \} {++$cnt} /, "\t $cnt -levels nested";' nest_test.txt
() 0 -levels nested
() 0 -levels nested
() 0 -levels nested
() 0 -levels nested
() 0 -levels nested
() 0 -levels nested
NOTA: Acima, tentei forçar algum tipo de 'comportamento recursivo frugal' usando <~~>*?
. A verdade é que <~~>
(notação recursiva padrão), <~~>?
, <~~>*
, e <~~>*?
todos dão resultados idênticos ( rakudo-moar-2024.09-01
).