78

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
    
    But 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?

AdminBee
  • 22,803
Raghvendra
  • 1,062

5 Answers5

87

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:

AdminBee
  • 22,803
Thomas Dickey
  • 76,765
23

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.

16

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).
AdminBee
  • 22,803
  • 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 04 '15 at 20:29
7

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.

cuonglm
  • 153,898
  • 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 – Alexander Cska Aug 27 '20 at 12:49
6

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).