Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

\n and \r's different behaviors under different circumstances in Vim

Tags:

vim

Say I have a line with just a character 's', let's go see \n's effect under different circumstances:

:s/s/a\nb
a^@b
:s/s/a\\nb
a\nb
:s/s/a\\\nb
a\^@b
:s/s/a\\\\nb
a\\nb

:echo "a\nb"
a
b
:echo "a\\nb"
a\nb
:echo "a\\\nb"
a\
b
:echo "a\\\\nb"
a\\nb

So why does \n behave differently? Then let's see the condition using substitute()

:echo substitute(" ", " ", "a\nb", "")
a
b
:echo substitute(" ", " ", "a\\nb", "")
a
b
:echo substitute(" ", " ", "a\\\nb", "")
a
b
:echo substitute(" ", " ", "a\\\\nb", "")
a\nb

This time, \n is still interpreted as "newline", but how to explain the backslash?

Next part, say I still have a line with just a character 's', instead of \n, \r is going to be studied:

:s/s/a\rb
a
b
:s/s/a\\rb
a\rb
:s/s/a\\\rb
a\
b
:s/s/a\\\\rb
a\\rb

\r's effect is like \n in :echo "a\nb", and the rule of backslash is the same.

:echo "a\rb"
b
:echo "a\\rb"
a\rb
:echo "a\\\rb"
b\  "This is the most strange case!!!
:echo "a\\\\rb"
a\\rb

What does \r do in this case? And the third subcase is even stranger.

:echo substitute(" ", " ", "a\rb", "")
b
:echo substitute(" ", " ", "a\\rb", "")
b
:echo substitute(" ", " ", "a\\\rb", "")
b
:echo substitute(" ", " ", "a\\\\rb", "")
a\rb

Still, I cannot understand how different number of backslashes behave.

My question are:

  1. Why does \n or \r behave differently under :substituteecho directly and substitute()?
  2. How to explain different number of backslashes' effect when using substitute()?
  3. What are the differences between \n and \r in Vim?

Supplement 1:

if I :let s = "a\\\nb" and then <C-r>=s to see it in the buffer, I see

a\
        b

How to explain this?

like image 265
fujianjin6471 Avatar asked Dec 24 '15 14:12

fujianjin6471


People also ask

Does vim automatically add newline?

A sequence of zero or more non- <newline> characters plus a terminating <newline> character. And, therefore, they all need to end with a newline character. That's why Vim always adds a newline by default (because, according to POSIX, it should always be there).

What is N in vim?

n is a default mapping in vim. In particular, n repeats the last search from the cursor's position down. You recently searched for "final" so that's what it searched for. In general, it is pretty easy to find out what a key does with :help <key> while in vim.

How do I go to a specific character in vim?

You can type f<character> to put the cursor on the next character and F<character> for the previous one. You can also use ; to repeat the operation and use , to repeat it in opposite direction.

How do we search backwards for a pattern use pattern for your answer vim?

One can search forward in vim/vi by pressing / and then typing your search pattern/word. To search backward in vi/vim by pressing ? and then typing your search pattern/word. Once word found in vim, you can press the n key to go directly to the next occurrence of the word in backwards.


1 Answers

  1. For both :echo and substitute(), \n is a newline and \r is a carriage return. They should do what you would expect. \n moves the cursor to the next line (column 1), and \r moves the cursor to column 1 same line. For \r the next character that gets printed will overwrite the previously print character. (I'm mostly focused on substitute() and :echo, :substitute is below)

  2. For why echo and substitute() behave differently. You need to understand how many interpretations of the string are happening. For echo only one happens for substitute() two happen.

    :echo substitute(" ", " ", "a\\\rb", "")
    b
    :echo substitute(" ", " ", 'a\\\rb', "")
    b\
    

The second is the same as what you would have expected for echo. Strings in double quotes have there contents changed according to :help expr-quote. This means that both echo and substitute see the same thing if the string is only interpreted once (which is using single quotes)

"a\\\rb" gets interpreted as a\rb after one interpretation and then a<CR>b after the second. Which leads to only b getting printed.

  1. \r and \n change depending on where they are used. The only difference would be :substitute where \r is used as a newline in the replacement.

This is one of the cases where :substitute and substitute() behave differently,

:substitue follows

  <CR>        split line in two at this point
              (Type the <CR> as CTRL-V <Enter>)                  s<CR>
  \r          idem                                               s/\r
  ...
  \n          insert a <NL> (<NUL> in the file)
              (does NOT break the line)                          s/\n

(<NUL> is the same as ^@ which is not the same as a newline)

while substitute() follows

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).
...
like image 85
FDinoff Avatar answered Sep 21 '22 04:09

FDinoff