O Melhor Truque de Regex é sobre escrever regexes que correspondem, r1
mas não r2
. O exemplo que eles dão é um regex que corresponde a Tarzan
(e "Tarzan and Jane"
), mas não "Tarzan"
. Depois de passar por algumas coisas que não funcionam, eles dão o "melhor truque de regex de todos os tempos":
"Tarzan"|(Tarzan)
Isso supostamente corresponde à "string ruim" primeiro, pulando a string boa, mas não incluindo a string ruim em um grupo de captura. Se apenas a string boa aparecer, nós correspondemos nela por último e a incluímos no grupo de captura.
Uma desvantagem do "melhor truque de regex" é que isso ainda corresponde a "Tarzan"
, mesmo que não o capture . Você não pode, por exemplo, usá-lo em um condicional sem algum boilerplate extra?
Isto é baseado em regexes estilo PCRE. O Raku usa uma notação regex completamente diferente. É possível fazer o truque de forma mais simples? Idealmente, isto deveria ser possível:
> ('"Tarzan"', 'Tarzan', '"Tarzan and Jane"') <<~~>> /some-regex/
(Nil 「Tarzan」 「Tarzan」)
Primeiro, um equivalente direto, mas idiomático, de "O Melhor Truque de Regex" no Raku:
Notas:
«op»
do operador meta do Raku para mapear sucintamente a correspondência em várias entradas. Usei isso mais a construção« ... »
de citação de termos do Raku para especificar sucintamente a entrada de correspondência.'"Tarzan"'
em vez de"Tarzan"
no padrão regex. Ao contrário dos dialetos regex mais antigos, o Raku trata o código da forma"foo"
em um regex como representando a string de três caracteresfoo
. Uma maneira de representar a string de cinco"foo"
caracteres é escrever'"foo"'
.(Tarzan)
captura de grupo é captura zero . Portanto, o códigosay
s.[0]
not.[1]
.Um passo que pode ser considerado na direção certa é:
Notas:
<(...)>
delimita explicitamente a captura de nível superior, estreitando-a em relação à captura de nível superior padrão (que captura tudo o que corresponde).<()>
significa que a captura de nível superior está vazia . Não éNil
, mas pode ser suficiente dependendo das suas necessidades.<(Tarzan)>
especifica a captura de nível superior (em contraste com(Tarzan)
o que especifica a primeira subcaptura ).A especificação original para regexes Raku incluía alguns recursos relevantes que ainda não foram implementados. É possível que eles sejam implementados um dia e forneçam uma solução mais simples.
Veja também a resposta de @tshiono.
Veja também a excelente resposta de @alatennaub no reddit .
Como você mencionou, o Raku usa uma notação regex completamente diferente. Você poderia tentar:
Resultado:
<!after \">
denota a afirmação negativa de olhar para trás.<!before \">
denota a afirmação de previsão negativa.|
pode ser cercada por espaços em branco.Isso é perto o suficiente?
Ou, um pouco mais claro na minha opinião:
Ou se você for usar o idioma "extrair a primeira captura de uma correspondência" o tempo todo, você pode até mesmo definir a composição de
~~
e[0]
como um novo operador (aqui,~~[0]
Mas isso provavelmente é um exagero! (E também tem que estar em uma linha no REPL devido a um bug).
(Tudo isso se baseia na excelente resposta do reddit de @alatennaub que @raiph já mencionou. Confira essa resposta para ver maneiras de evitar a correspondência com `"Tarzan"', o que evita a necessidade de selecionar a primeira captura)
Como sempre, aprendi muito com @raiph e esta resposta é um pequeno refinamento da dele, espero que com um pouco mais de espaço:
Notas:
« ... »
termo citação@tests
eregex
separadamente~
til para equilibrar a correspondência de ambos"