:h nl-used-for-nul
объясняет, что символ новой строки '\n'
отображается Vim как ^@
. Итак, да, как вы уже сказали, вы отправляете фактические символы новой строки в оболочку.
Далее, общая идея замены одного символа '\n'
(ASCII 0x0a) на два символа "\n"
(0x5c 0x6e) также верна. Вы хотите, чтобы оболочка получила foo\nbar
.
:echo substitute(@m, '\n', '\n', 'g')
a
ab
abc
abce
abcef
abcefg
Вывод, очевидно, по-прежнему содержит символы новой строки, поэтому мы должны их избежать.
:echo substitute(@m, '\n', '\\n', 'g')
a\nab\nabc\nabce\nabcef\nabcefg\n
Это выглядит хорошо! Итак, давайте попробуем всю команду, которую вы имели в виду:
:execute '!echo' substitute(@m, '\n', '\\n', 'g')
anabnabcnabcenabcefnabcefgn
Press ENTER or type command to continue
Хм? Ну, :execute
оценивает строки и поэтому потребляет"один уровень строк". Таким образом, мы должны еще раз избежать наших новых строк, тогда как удваиваем количество экранирований для каждого "уровня строк".
Итак, нам не просто нужны a\nab\nabc
, нам нужны a\\nab\\nabc
:
:echo substitute(@m, '\n', '\\\\n', 'g')
a\\nab\\nabc\\nabce\\nabcef\\nabcefg\\n
:execute '!echo' substitute(@m, '\n', '\\\\n', 'g')
a
ab
abc
abce
abcef
abcefg
Press ENTER or type command to continue
?
Дополнительные примечания:
- При использовании двойных кавычек, которые обрабатывают escape-символы, в отличие от строк в одинарных кавычках, нам придется снова удваивать количество экранированных символов:
substitute(@m, '\n', "\\\\\\\\n", 'g')
.
- Если вы хотите удалить завершающий символ новой строки, используйте
trim(@)
.