!rm`.*$
With a single regex, Retina runs in Match mode. This normally just prints the number of matches, but with !
we configure it to print the actual matches instead (separated by linefeeds).
The actual regex is merely .*$
. .*
matches any line (potentially empty), because .
can match any character except linefeeds. I'll get to the $
in a minute.
How do we make it print the matches in reverse? By making use of .NET's right-to-left matching mode, activated with the r
. This means the regex engine starts at the end of the string when looking for matches and works backwards.
Finally, the m
makes the $
match the end of a line instead of the end of the string. Why do we even need that? The trouble is that .*
generates extraneous matches. Consider the regex substitution
s/a*/$0x/
applied to the input baaababaa
. You'd think this would yield baaaxbaxbaax
, but it actually gives you baaaxxbaxxbaaxx
. Why? Because after matching aaa
the engine's cursor is between the a
and the b
. Now it can't match any more a
s, but a*
is also satisfied with an empty string. This means, after every single match you get another empty match.
We don't want that here, because it would introduce additional empty lines, so we discard those extraneous matches (which are at the beginnings of the lines, due to the right-to-left mode) by requiring that matches include the end of the line.
tac
is a bit strange when it comes to trailing linefeeds. It transformsa\nb\n
(trailing linefeed) intob\na\n
anda\nb
(no trailing linefeed) intoba\n
. Is this how our code it supposed to behave? \$\endgroup\$tac
is only a matter of time... \$\endgroup\$\n
.tac
reverses the order of these rows. If an\n
is removed from the middle of the file, the row it terminated is joined to the next row, but in the case of the last line, there is no next row to join to. \$\endgroup\$