!rm`.*$
Avec une seule expression régulière, Retina s'exécute en mode Match. Cela n'imprime normalement que le nombre de correspondances, mais avec !
nous le configurons pour imprimer les correspondances réelles à la place (séparées par des sauts de ligne).
Le regex réel est simplement .*$
. .*
correspond à n'importe quelle ligne (potentiellement vide), car .
peut correspondre à n'importe quel caractère à l'exception des sauts de ligne. J'y arriverai $
dans une minute.
Comment faire imprimer les allumettes à l'envers? En utilisant le mode de correspondance de droite à gauche de .NET, activé avec le r
. Cela signifie que le moteur d'expression régulière démarre à la fin de la chaîne lors de la recherche de correspondances et fonctionne à l'envers.
Enfin, le m
fait $
correspondre la fin d'une ligne au lieu de la fin de la chaîne. Pourquoi en avons-nous même besoin? Le problème est que cela .*
génère des correspondances étrangères. Considérez la substitution d'expression régulière
s/a*/$0x/
appliqué à l'entrée baaababaa
. Vous penseriez que cela donnerait baaaxbaxbaax
, mais cela vous donne en fait baaaxxbaxxbaaxx
. Pourquoi? Parce qu'après avoir fait correspondre aaa
le curseur du moteur se trouve entre le a
et le b
. Maintenant, il ne peut plus correspondre à a
s, mais il a*
est également satisfait d'une chaîne vide. Cela signifie qu'après chaque match, vous obtenez un autre match vide.
Nous ne voulons pas cela ici, car cela introduirait des lignes vides supplémentaires, donc nous supprimons ces correspondances étrangères (qui sont au début des lignes, en raison du mode de droite à gauche) en exigeant que les correspondances incluent la fin la ligne.
tac
est un peu étrange en ce qui concerne les sauts de ligne de fin. Il transformea\nb\n
(saut de ligne arrière) enb\na\n
eta\nb
(pas de saut de ligne arrière) enba\n
. Est-ce ainsi que notre code devrait se comporter?