56

In vim editor, I want to replace a newline character (\n) with two new line characters (\n\n) using vim command mode.

Input file content:

This is my first line.
This is second line.

Command that I tried:

:%s/\n/\n\n/g

it replaces the string with unwanted characters as

This is my first line.^@^@This is second line.^@^@

Then I tried the following command

:%s/\n/\r\r/g

It is working properly. Can you explain why it is working fine with second command?

4
71

Oddly enough, \n in vim for replacement does not mean newline, but null. ASCII nul is ^@ (Ctrl+@).

Historically, vi replaces ^M (Ctrl+M) as the line-ending, which is the newline. vim added an extension \r (like the C language) to mean the same as ^M, but the developers chose to make \n mean null when replacing text. This is inconsistent with its use in searches, which find a newline.

Further reading:

2
  • 6
    This does not answer the question.
    – Jortstek
    Apr 29 '20 at 6:26
  • @Jortstek That depends. The question title asks "how", but the actual question asks "why", and that is explained in this answer.
    – AdminBee
    Aug 6 '20 at 9:34
13

Try this:

%s/$/^V^M/

where ^V is Ctrl+V and ^M is Ctrl+M.

  • When you type ^V it will print a ^ char, then Backspace over it and then when you type the ^M it will appear as ^M
  • The Ctrl+V is the standard tty literal next character - run the command stty -a to show your tty's special chars).
1
  • Indeed, the very experienced will know this for the ever required conversion from CRLF as an alternative to dropping out and using dos2unix or similar. The Ctrl-V usage is a day 1 vi lesson.
    – mckenzm
    Dec 4 '15 at 20:29
6

vim use \n to represent a null character \0 in memory, that how vim handle file contain null character (while vi can not).

The use of \n only match end of line in the buffer, not the newline in the string when using in expression.

See :h NL-used-for-Null and :h CR-used-for-NL for more details.

1
  • g/^\(.*\)\n\1$/d is \n here interpreted as a new line? Skipping \n will leave only the last line, instead of deleting the duplicates only. For instance s/a b/a\nb won't work, however, s/a b/a\rb will i.e. space is replaced with new line between a and b Aug 27 '20 at 12:49
4

Tested with Neovim (nvim) and Vim versions

NVIM v0.3.0
VIM - Vi IMproved 8.1

Remove a newline:

cell
allele
rs2981578
fgfr2

Here, \n matches newlines (to insert a newline however, use \r):

:'<,'>s/\n/|/g

cell|allele|rs2981578|fgfr2

Add a newline:

Nope:

cell|allele|rs2981578|fgfr2

:'<,'>s/\n/|/g

cell^@allele^@rs2981578^@fgfr2

^@ is a diacritic mark for LF (line feed; see http://vimhelp.appspot.com/digraph.txt.html#digraphs-default)

Yes:

cell|allele|rs2981578|fgfr2

:'<,'>s/|/\r/g

cell
allele
rs2981578
fgfr2

To address the OP's question (how to replace one \n with two, \n\n), just add another \r:

cell
allele
rs2981578
fgfr2

:'<,'>s/\n/\r\r/g

cell

allele

rs2981578

fgfr2

... i.e. match the original newline (\n), and replace it with two newlines/carriage returns (\r\r).

4

To replace 1 newline with 2 newlines: :%s/\n/\r\r/g

\n - newline in search, null in replace

\r - newline in replace

Answer is in the question, author asked 'how to' in title, but 'why' in content... People enter this page looking for answer to 'how to' and you don't really expect it to be in question... took me a while to figure that out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.