why does vim has different escape character for newline between searching and replacing [duplicate] - vim

From question How to replace a character for a newline in Vim?. You have to use \r when replacing text for a newline, like this
:%s/%/\r/g
But when replacing end of lines and newlines for a character, you can do it like:
:%s/\n/%/g
What section of the manual documents these behaviors, and what's the reasoning behind them?

From http://vim.wikia.com/wiki/Search_and_replace :
When Searching
...
\n is newline, \r is CR (carriage return = Ctrl-M = ^M)
When Replacing
...
\r is newline, \n is a null byte (0x00).

From vim docs on patterns:
\r matches <CR>
\n matches an end-of-line -
When matching in a string instead of
buffer text a literal newline
character is matched.

Another aspect to this is that \0, which is traditionally NULL, is taken in
s//\0/ to mean "the whole matched pattern". (Which, by the way, is redundant with, and longer than, &).
So you can't use \0 to mean NULL, so you use \n
So you can't use \n to mean \n, so you use \r.
So you can't use \r to mean \r, but I don't know who would want to add that char on purpose.
—☈

:help NL-used-for-Nul
Technical detail:
<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}

First of all, open :h :s to see the section "4.2 Substitute" of documentation on "Change". Here's what the command accepts:
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
Notice the description about pattern and string
For the {pattern} see |pattern|.
{string} can be a literal string, or something
special; see |sub-replace-special|.
So now you know that the search pattern and replacement patterns follow different rules.
If you follow the link to |pattern|, it takes you to the section that explains the whole regexp patterns used in Vim.
Meanwhile, |sub-replace-special| takes you to the subsection of "4.2 Substitute", which contains the patterns for substitution, among which is \r for line break/split.
(The shortcut to this part of manual is :h :s%)

Related

How to search for all occurrences of the string `**` in a file using vim?

How to search for ** in a file using vim like **kwargs , when I use a /** it highlights the entire file.
* is a meta-character that needs to be escaped to become a regular character:
/\*\*
Vim refers to this as "magic": if the pattern is "magic", you need to escape meta-characters, if it is "nomagic", you don't (this is a bit over-simplified, see :help magic).
Therefore, you can force Vim to treat the pattern as "nomagic" with \M or even "very nomagic", with \V:
/\V**
Which doesn't help much, here, but well…
As for why /** highlights the whole buffer, a hint can be found under :help /star:
Exception: When "*" is used at the start of the pattern or just after
"^" it matches the star character.
The first * matches (at least some of) the stars in your buffer,
The second * matches zero or more of the preceding atom, as many as possible, so, essentially, every character.
You have to escape the * symbol, try
/\*\*
On the text below I added extra spaces to be easier to read
#Don't use this one / \* \*

^M vs \n in vim string replacement

There seems to be some sort of asymmetry in the way Vim treats ^M when doing string replacement (:s/x/y/).
Perhaps an example is best; say we have this text file:
foo:bar:biz
I want to split this into lines. This works fine:
:s/:/^M/g
(note that ^M is produced by typing Ctrl-V, Enter)
This results in the text file:
foo
bar
baz
Now, if I undo that and try again, I notice that this does not work:
:s/:/\n/g
Here, the resulting text is:
foo^#bar^#biz
That is to say, they are joined by the ASCII NUL byte (0x00).
Question 1: Why does using \n in the replacement result in NUL bytes?
Now, I figure "okay, I guess ^M is used as the 'line separator' character in some way, for Vim; I can work with that".
So I do another experiment, starting with the one-item-per-line text file:
foo
bar
baz
and now, I want to join them with colons, so it looks like the very first incarnation, above.
So I run:
:%s/^M/:/
But this fails, with the error:
E486: Pattern not found: ^M
However, this command does work:
:%s/\n/:/
producing:
foo:bar:biz:
(I can get rid of the trailing colon myself)
So Question 2: Why does \n work in this case, where ^M does not?
And ultimately, Question 3: Why is there this asymmetry between \n and ^M depending on whether it's on the right- or left-hand side of a string replacement command?
When searching, \n is a "catch-all" atom that conveniently matches any kind of "end-of-line": CRLF, CR, and LF.
When replacing, \n is <Nul> and represented as ^#.
When replacing, \r is the legal "end-of-line" for the current fileformat.
In short, get used to this pattern and carry on:
:s/\n/\r
See :help NL-used-for-Nul and CR-used-for-NL.

vi replaces with empty when searching

In vi (from cygwin), when I do searching:
:%s/something
It just replaces the something with empty string like
:%s/something// .
I've googled for a while but nothing really mentions this. Is there anything I should add to the .vimrc or .exrc to make this work?
Thanks!
In vi and vim, when you search for a pattern, you can search it again by simply typing /. It is understood that the previous pattern has to be used when no pattern is specified for searching.
(Though, you can press n for finding next occurence)
Same way, when you give a source (pattern) and leave the replacement in substitute command, it assumes that the replacement is empty and hence the given pattern is replaced with no characters (in other words, the pattern is removed)
In your case, you should understand that % stand for whole file(buffer) and s for substitute. To search, you can simply use /, followed by a pattern. To substitute , you will use :s. You need not confuse searching and substituting. Hence, no need for such settings in ~/.exrc. Also, remember that / is enough to search the whole buffer and % isnt necessary with /. / searches the entire buffer implicitly.
You may also want to look at :g/Pattern/. Learn more about it by searching :help global or :help :g in command line.
The format of a substitution in vim is as follows:
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
In your case you have omitted the string from the substitution command and here what vim documentation stated about it:
If the {string} is omitted the substitute is done as if it's empty.
Thus the matched pattern is deleted. The separator after {pattern}
can also be left out then. Example: >
:%s/TESTING This deletes "TESTING" from all lines, but only one per line.
For compatibility with Vi these two exceptions are allowed:
"/{string}/" and "\?{string}?" do the same as "//{string}/r".
"\&{string}&" does the same as "//{string}/".
E146
Instead of the '/' which surrounds the pattern and replacement string, you can
use any other single-byte character, but not an alphanumeric
character, '\', '"' or '|'. This is useful if you want to include a
'/' in the search pattern or replacement string. Example: >
:s+/+//+
In other words :%s/something and :%s;something or :%s,something have all the same behavior because the / ; and , in the last examples are considered only as SIMPLE SEPARATOR

Vim Search/replace: what do I need to escape?

I'm trying to search and replace $data['user'] for $data['sessionUser'].
However, no matter what search string I use, I always get a "pattern not found" as the result of it.
So, what would be the correct search string? Do I need to escape any of these characters?
:%s/$data['user']/$data['sessionUser']/g
:%s/\$data\[\'user\'\]/$data['sessionUser']/g
I did not test this, but I guess it should work.
Here's a list of all special search characters you need to escape in Vim: `^$.*[~)+/
There's nothing wrong with with the answers given, but you can do this:
:%s/$data\['\zsuser\ze']/sessionUser/g
\zs and \ze can be used to delimit the part of the match that is affected by the replacement.
You don't need to escape the $ since it's the at the start of the pattern and can't match an EOL here. And you don't need to escape the ] since it doesn't have a matching starting [. However there's certainly no harm in escaping these characters if you can't remember all the rules. See :help pattern.txt for the full details, but don't try to digest it all in one go!
If you want to get fancy, you can do:
:%s/$data\['\zsuser\ze']/session\u&/g
& refers to the entire matched text (delimited by \zs and \ze if present), so it becomes 'user' in this case. The \u when used in a replacement string makes the next character upper-case. I hope this helps.
Search and replace in vim is almost identical to sed, so use the same escapes as you would with that:
:%s/\$data\['user'\]/$data['session']/g
Note that you only really need to escape special characters in the search part (the part between the first set of //s). The only character you need to escape in the replace part is the escape character \ itself (which you're not using here).
The [ char has a meaning in regex. It stands for character ranges. The $ char has a meaning too. It stands for end-line anchor. So you have to escape a lot of things. I suggest you to try a little plugin like this or this one and use a visual search.

Why is \r a newline for Vim?

From question How to replace a character for a newline in Vim?. You have to use \r when replacing text for a newline, like this
:%s/%/\r/g
But when replacing end of lines and newlines for a character, you can do it like:
:%s/\n/%/g
What section of the manual documents these behaviors, and what's the reasoning behind them?
From http://vim.wikia.com/wiki/Search_and_replace :
When Searching
...
\n is newline, \r is CR (carriage return = Ctrl-M = ^M)
When Replacing
...
\r is newline, \n is a null byte (0x00).
From vim docs on patterns:
\r matches <CR>
\n matches an end-of-line -
When matching in a string instead of
buffer text a literal newline
character is matched.
Another aspect to this is that \0, which is traditionally NULL, is taken in
s//\0/ to mean "the whole matched pattern". (Which, by the way, is redundant with, and longer than, &).
So you can't use \0 to mean NULL, so you use \n
So you can't use \n to mean \n, so you use \r.
So you can't use \r to mean \r, but I don't know who would want to add that char on purpose.
—☈
:help NL-used-for-Nul
Technical detail:
<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}
First of all, open :h :s to see the section "4.2 Substitute" of documentation on "Change". Here's what the command accepts:
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
Notice the description about pattern and string
For the {pattern} see |pattern|.
{string} can be a literal string, or something
special; see |sub-replace-special|.
So now you know that the search pattern and replacement patterns follow different rules.
If you follow the link to |pattern|, it takes you to the section that explains the whole regexp patterns used in Vim.
Meanwhile, |sub-replace-special| takes you to the subsection of "4.2 Substitute", which contains the patterns for substitution, among which is \r for line break/split.
(The shortcut to this part of manual is :h :s%)

Resources