На самом базовом уровне уже есть асимметрия между частями поиска и замены, :substitute
потому что первое - это регулярное выражение, а второе - текст, с конкретными дополнительными escape-последовательностями . Это просто подчеркивается вашей интуицией о том, что \n
значит.
Например, учтите, что \n
в поиске не соответствует литералу \n
. Это соответствует концу строки (EOL) последовательности байтов, которые могут быть \r
, \r\n
или просто в \n
зависимости от 'fileformat'
буфера.
Что касается того, почему \r
используется для обозначения «вставить EOL», за этим стоит некоторая история . У Ви не было возможности обработать NUL-байт в файле. Vim улучшил это, заменив байты NUL внутренним байтом NL (поскольку строки C разделены NUL).
Эта деталь реализации просочилась в поведение, :substitute
поскольку \n
при замене просто вставляется во внутреннее представление этой строки, которое используется для указания байта NUL. \r
вставляет EOL, разбивая внутреннюю строку на две части. На самом деле Vim не хранит байты EOL в памяти, а де-сериализует их при чтении / записи в буфер.
Это нельзя изменить сейчас, не нарушая множество скриптов и мышечной памяти многих пользователей. К счастью, это задокументировано в :help sub-replace-special
.
\r
есть<CR>
и\n
есть<LF>
. Это не относится к актуальному вопросу о том, почему\n\r
ведут себя по- разному в разных контекстах.