!rm`.*$
Com um único regex, o Retina é executado no modo de correspondência. Normalmente, isso apenas imprime o número de correspondências, mas, com !
isso, configuramos para imprimir as correspondências reais (separadas por linhas de alimentação).
O regex real é apenas .*$
. .*
corresponde a qualquer linha (potencialmente vazia), porque .
pode corresponder a qualquer caractere, exceto feeds de linha. Eu vou chegar $
em um minuto.
Como podemos imprimir as correspondências ao contrário? Utilizando o modo de correspondência da direita para a esquerda do .NET, ativado com o r
. Isso significa que o mecanismo regex inicia no final da string ao procurar correspondências e funciona ao contrário.
Finalmente, m
faz com que a $
correspondência seja o final de uma linha, em vez do final da sequência. Por que precisamos disso? O problema é que .*
gera correspondências estranhas. Considere a substituição de regex
s/a*/$0x/
aplicado à entrada baaababaa
. Você pensaria que isso renderia baaaxbaxbaax
, mas realmente lhe dá baaaxxbaxxbaaxx
. Por quê? Porque, depois de corresponder, aaa
o cursor do mecanismo fica entre o a
e o b
. Agora não pode mais corresponder a
s, mas a*
também está satisfeito com uma sequência vazia. Isso significa que, após cada partida, você recebe outra partida vazia.
Não queremos isso aqui, porque isso introduziria linhas vazias adicionais; portanto, descartamos essas correspondências estranhas (que estão no início das linhas, devido ao modo da direita para a esquerda), exigindo que as correspondências incluam o final de a linha.
tac
é um pouco estranho quando se trata de rastrear feeds de linha. Ele transformaa\nb\n
(avanço de linha à direita) emb\na\n
ea\nb
(sem avanço de linha à direita) emba\n
. É assim que nosso código deveria se comportar?