We all know that, when searching, \n is newline and \r is carriage return (^M), but when replacing \r is newline while \n is a null byte (^@).What is the origin of this asymmetry? Given that this behavior is... peculiar to say the least (and quite counterproductive when you get it wrong the first time) I expect there's some bizarre historical reason.(incidentally, is there some way to fix this behavior and get something more intuitive?)
What is the rationale for \r and \n meaning different things in s command?
regular expression;substitute;whitespace;history of
At the most basic level, there's already an asymmetry between the search and replace portions of :substitute because the former is a regular expression and the latter is text, with specific additional escape sequences.  This is just highlighted by the intuition you have about what \n means.For example, consider that \n in the search doesn't match a literal \n.  It matches the end of line (EOL) byte sequence, which may be \r, \r\n, or just \n depending on the 'fileformat' of the buffer.As far as why \r is used to mean insert an EOL, there's some history behind that.  Vi had no way to handle a NUL byte in a file.  Vim improved on that by replacing NUL bytes with an NL byte internally (since C strings are NUL delimited).This implementation detail leaked into the behavior of :substitute since \n in the replacement is simply inserted into the internal representation of that line, which is used to indicate a NUL byte.  \r inserts an EOL, breaking the internal line in two.  Vim doesn't actually store the EOL bytes in memory, instead (de)serializing them when reading/writing the buffer.It can't be changed now without breaking the many scripts and the muscle memory of many users.  Thankfully, it's documented in :help sub-replace-special.