!rm`.*$
Mit einem einzigen regulären Ausdruck wird Retina im Match-Modus ausgeführt. Dies gibt normalerweise nur die Anzahl der Übereinstimmungen aus, aber mit! wir konfigurieren es stattdessen so, dass die tatsächlichen Übereinstimmungen gedruckt werden (durch Zeilenvorschübe getrennt).
Der eigentliche reguläre Ausdruck ist lediglich .*$. .*Stimmt mit jeder Zeile überein (möglicherweise leer), da .sie mit jedem Zeichen außer Zeilenvorschub übereinstimmen kann. Ich komme zum$ .
Wie bringen wir es dazu, die Übereinstimmungen in umgekehrter Reihenfolge auszudrucken? Verwenden Sie den von rechts nach links abgleichenden Modus von .NET, der mit aktiviert wirdr . Dies bedeutet, dass die Regex-Engine bei der Suche nach Übereinstimmungen am Ende der Zeichenfolge startet und rückwärts arbeitet.
Schließlich mwird die $Übereinstimmung mit dem Ende einer Zeile anstelle des Endes der Zeichenfolge hergestellt. Warum brauchen wir das überhaupt? Das Problem ist, dass .*irrelevante Übereinstimmungen entstehen. Betrachten Sie die Regex-Substitution
s/a*/$0x/
auf den Eingang angewendet baaababaa. Sie würden denken, dies würde nachgeben baaaxbaxbaax, aber es gibt Ihnen tatsächlich baaaxxbaxxbaaxx. Warum? Denn nach dem Abgleichen befindet sich aaader Cursor des Motors zwischen dem aund dem b. Jetzt kann es nicht mehr mit as übereinstimmen , sondern a*ist auch mit einem leeren String zufrieden. Dies bedeutet, dass Sie nach jedem einzelnen Spiel ein weiteres leeres Spiel erhalten.
Wir wollen das hier nicht, weil es zusätzliche Leerzeilen einführen würde, also verwerfen wir diese irrelevanten Übereinstimmungen (die aufgrund des Modus von rechts nach links am Anfang der Zeilen stehen), indem wir verlangen, dass Übereinstimmungen das Ende von enthalten die Linie.
tacist etwas seltsam, wenn es um nachgestellte Zeilenvorschübe geht. Es wandelt sich ina\nb\n(Trailing Linefeed)b\na\nund ina\nb(No Trailing Linefeed) umba\n. Soll sich unser Code so verhalten?