'Why does Vim on windows use \n for searching?
So I was changing code from
foo()
{
to
foo() {
and I noticed that the searching pattern required me to search for \n
, but when I tried to replace it with \n
I got the ^@
character, and I had to instead replace with \r
.
It seems strange to me that I search with \n
and replace with \r
, any idea why this might be?
For reference my solution was :%s/\n\s*{/ {\r/g
Solution 1:[1]
The syntax for the search part and replacement part are arbitrarily different. Some of the same codes are re-used to mean different things. Yeah, it's confusing.
| How to type | In search, means: | In replacement, means:
----------------------------------------------------------------------------
\n | \n | End-of-line | <Nul> 0x0
^@ | CTRL-V CTRL-J | <Nul> 0x0 | <Nul> 0x0
\r | \r | Carriage return 0xD | "Break the line here"
^M | CTRL-Enter | Carriage return 0xD | "Break the line here"
\^M | \ CTRL-V CTRL-ENTER | \ + carriage return 0xD | Carriage return 0xD
When searching, depending on your platform, the 0xD
may be hidden, considered part of "newline", so yeah... you can always return sanity to your files and force all of the carriage returns displayed by opening a file and doing:
:e ++ff=unix
Similarly when replacing, "break the line here" does different things depending on your platform. It might insert 0xA
or 0xD 0xA
etc.
In case this isn't all already bad enough:
Technical detail: *NL-used-for-Nul*
<Nul> characters in the file are stored as <NL> in memory. In the display
they are shown as "^@". The translation is done when reading and writing
files. To match a <Nul> with a search pattern you can just enter CTRL-@ or
"CTRL-V 000". This is probably just what you expect. Internally the
character is replaced with a <NL> in the search pattern. What is unusual is
that typing CTRL-V CTRL-J also inserts a <NL>, thus also searches for a <Nul>
in the file. {Vi cannot handle <Nul> characters in the file at all}
*CR-used-for-NL*
When 'fileformat' is "mac", <NL> characters in the file are stored as <CR>
characters internally. In the text they are shown as "^J". Otherwise this
works similar to the usage of <NL> for a <Nul>.
When working with expression evaluation, a <NL> character in the pattern
matches a <NL> in the string. The use of "\n" (backslash n) to match a <NL>
doesn't work there, it only works to match text in the buffer.
Unless dealing with literal 0x0
or 0xD
characters, it's agood a rule of thumb to always stick with \n
for search and \r
for replacement, as you've probably figured out.
See also:
:h /\n
:h /\r
:h s/\n
:h s/\r
:h s/\<CR>
Solution 2:[2]
I think your problem is due to the fact that Unix-like operating systems like Linux use the newline (aka "linefeed") (0x0A) as the end of line marker, but Windows uses carriage return + newline (0x0D 0x0A). vim is trying to do some sort of mapping to make the Windows two-byte end of line look like a single "end of line".
In a related note, the following command seems to convert a Unix-style file to a Windows one on a Windows machine, and convert a Windows-style file to a Unix one on a Unix machine:
:%s/^V^M/^V^M/g
where ^V
means hold the control key and press the V, and similarly ^M
means hold the control key and press M.
Solution 3:[3]
I gave up understanding clearly or remembering all about <NL>
, <CR>
etc., which is too complex and not used frequently.
When I use them, just try.
In case this isn't all already bad enough:
:h sub-replace-special
The special meaning is also used
inside the third argument {sub} of the |substitute()| function
with the following exceptions:
. <CR> and \r inserts a carriage-return (CTRL-M).
. \<CR> does not have a special meaning. It's just one of \x.
. A ~ inserts a tilde literally.
. magic is always set without regard to 'magic'.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Brian Carper |
Solution 2 | Paul Tomblin |
Solution 3 |