I’m trying to replace each
, in the current file by a new line:
But it inserts what looks like a
^@ instead of an actual newline. The file is not in DOS mode or anything.
What should I do?
If you are curious, like me, check the question Why is \r a newline for Vim? as well.
\r instead of
\n inserts a null character into the text. To get a newline, use
\r. When searching for a newline, you’d still use
\n, however. This asymmetry is due to the fact that
\r do slightly different things:
\n matches an end of line (newline), whereas
\r matches a carriage return. On the other hand, in substitutions
\n inserts a null character whereas
\r inserts a newline (more precisely, it’s treated as the input CR). Here’s a small, non-interactive example to illustrate this, using the Vim command line feature (in other words, you can copy and paste the following into a terminal to run it).
xxd shows a hexdump of the resulting file.
echo bar > test (echo 'Before:'; xxd test) > output.txt vim test '+s/b/\n/' '+s/a/\r/' +wq (echo 'After:'; xxd test) >> output.txt more output.txt
Before: 0000000: 6261 720a bar. After: 0000000: 000a 720a ..r.
In other words,
\n has inserted the byte 0x00 into the text;
\r has inserted the byte 0x0a.
Here’s the trick:
First, set your Vi(m) session to allow pattern matching with special characters (i.e.: newline). It’s probably worth putting this line in your .vimrc or .exrc file:
To get the
^M character, type Ctrl + V and hit Enter. Under Windows, do Ctrl + Q, Enter. The only way I can remember these is by remembering how little sense they make:
A: What would be the worst control-character to use to represent a newline?
q(because it usually means “Quit”) or
vbecause it would be so easy to type Ctrl + C by mistake and kill the editor.
A: Make it so.
In the syntax
\n have different meanings, depending on context.
\r == “carriage return” (
\n == matches “line feed” (
LF) on Linux/Mac, and
CRLF on Windows
\r == produces
LF on Linux/Mac,
CRLF on Windows
\n == “null byte” (
When editing files in linux (i.e. on a webserver) that were initially created in a windows environment and uploaded (i.e. FTP/SFTP) – all the
^M‘s you see in vim, are the
CR‘s which linux does not translate as it uses only
LF‘s to depict a line break.
Longer (with ASCII numbers):
NUL == 0x00 == 0 == Ctrl + @ ==
^@ shown in vim
LF == 0x0A == 10 == Ctrl + J
CR == 0x0D == 13 == Ctrl + M ==
^M shown in vim
Here is a list of the ASCII control characters. Insert them in Vim via Ctrl + V,Ctrl + ---key---.
In Bash or the other Unix/Linux shells, just type Ctrl + ---key---.
Try Ctrl + M in Bash. It’s the same as hitting Enter, as the shell realizes what is meant, even though Linux systems use line feeds for line delimiting.
To insert literal’s in bash, prepending them with Ctrl + V will also work.
Try in Bash:
echo ^[[33;1mcolored.^[[0mnot colored.
This uses ANSI escape sequences. Insert the two
^[‘s via Ctrl + V, Esc.
You might also try Ctrl + V,Ctrl + M, Enter, which will give you this:
bash: $'\r': command not found
\r from above? :>
This ASCII control characters list is different from a complete ASCII symbol table, in that the control characters, which are inserted into a console/pseudoterminal/Vim via the Ctrl key (haha), can be found there.
Whereas in C and most other languages, you usually use the octal codes to represent these ‘characters’.
If you really want to know where all this comes from: The TTY demystified. This is the best link you will come across about this topic, but beware: There be dragons.