Vim Search/Replace, meaning of %s - vim

In Vim you can search/replace text in the following way.
:%s/old/new
What does the %s mean?

% is the range over which the :s command (short for :substitute) will be run. % itself is short for the range :1,$, which means Line 1 to the last line in the buffer.
The Vim help has a couple topics (user manual - :help 10.3, reference manual - :help cmdline-ranges) describing the forms that ranges can take.

The syntax for :s (which is short for :substitute) is:
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
The % range means "the whole file".
This is very powerful; if you would want to do substitutions on just line 1, you would use:
:1s/a/b/
Or, for just lines 1 to 3:
:1,3s/a/b/
A very useful (related) trick, is to highlight lines with visual mode (V), and then use :s to substitute just on the lines you highlighted.
See: :help [range]

:%s/old/new/
This will search the entire document for "old" and replace the first instance on each line with "new". You can use :%s/old/new/g to replace all instances of "old" with "new".
(Updated based answer on jamessan's comment).

%s stands for the whole document. See here:
http://vim.wikia.com/wiki/Ranges

Related

Is there any way to enclose a variable with print() statement or any function in vim especially using vim vs code extension

suppose I have a variable named
a_variable
is there a surround or some combination of keystrokes which will do
print(a_variable)
or
print("a_variable: ", a_variable)
when my cursor in on the line where a_variable is defined ?
I could not find any relevant material on the web .
Any help is appreciated.
This answers is written with Vim in mind. Some, all, or none of it may apply to your specific Vim emulator so YMMV.
With the surround plugin
First case
You can position your cursor on a_variable and do:
ysiwfprint(<CR>
to obtain:
print(a_variable)
Second case
It is currently impossible to achieve with surround only.
Without surround
First case
You can position your cursor on a_variable and do:
ciwprint(<C-r>")<Esc>
Second case
The scond case is a variant of the first case where you insert the variable name two times instead of one:
ciwprint("<C-r>": ", <C-r>")<Esc>
Turn it into a mapping if you need to do it often.
See :help c, :help iw, :help i_ctrl-r, :help "".

I need to replace the second occurrence of string1 by string2 on every line - vim

I know that there are multiple occurrences of string1 in every line of the file. I am looking for the shortest/quickest way to replace the second one by string2. Any method will do though vim is my preference.
You can find the second occurrence of "string1" using \zs.
Based on the :h \zs example, it will be
:%s/\(.\{-}\zsstring1\)\{2}/string2
It'll be more straightforward using external sed in Vim command mode
:%!sed 's/string1/string2/2'
See https://vi.stackexchange.com/questions/8621/substitute-second-occurence-on-line for more ways to accomplish it.
Here is one way:
:%normal 0/string1^Mncgnstring2<CR>
Breakdown:
:[range]normal <macro> executes normal mode <macro> on every line in [range],
% is a shorthand for range [<first line>,<last line>], which covers every line in the buffer,
0 is the first command of our macro, it places the cursor on the first column of the line, which is a good habit to have,
/string1^M moves the cursor to the first match for string1, the ^M is a literal <CR> obtained with <C-v><CR>,
n moves the cursor to to the next match,
cgnstring2 changes the current match to string2.
See :help :range, :help :normal, :help gn.
But it would have been more interesting to see what you tried and fix it, rather than provide you with a working solution.

What is the meaning of the % character in vim?

The vim wikia page provides the following description for search and replace:
:%s/foo/bar/g
Find each occurrence of 'foo' (in all lines), and replace it with 'bar'.
:s/foo/bar/g
Find each occurrence of 'foo' (in the current line only), and replace it with 'bar'.
...
I can see that the the % character causes the whole buffer to be searched.
What is the meaning of the % character in vim? Is it a variable that refers to the current buffer?
Learn how to look up commands and navigate the built-in :help; it is comprehensive and offers many tips. You won't learn Vim as fast as other editors, but if you commit to continuous learning, it'll prove a very powerful and efficient editor.
Here's how you would have found the information:
Look up the command: :help :substitute
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
Ah, the stuff in front is called range. Further down, there's a link to it:
Also see |cmdline-ranges|.
(:help [range] would have also taken you to it.) And that explains the meaning of %, as well as the help keyword for direct access.
% equal to 1,$ (the entire file) *:%*

Vim - Find pattern on currently line ONLY

I'm wondering if there is a way to find a pattern, but restrict it to the current line. Basically, the equivalent of /PATTERN but restricted to the current line, rather than the entire document.
I've tried :s/PATTERN, but that deletes the pattern from the line and places my cursor at the beginning of the line, which is not at all what I need. I was hoping you could search without replacing...
I'm hoping to use this for a macro in order to place my cursor at the start of that pattern, as would happen when you do /PATTERN on the entire file, so anything that is macro-friendly is even better.
Any vim users out there that might have an idea?
EDIT: 0/PATTERN in a macro would work for my current need, but I'm hoping there's a more specific way to restrict the search.
ANSWER: There's a few ways posted in here so far, but the one I like best right now is using Shift+V to select the current line visually, followed by /\%V to search only in the visual selection. Then Shift+V again will turn off the visual mode.
My knowledge about macro is limited, but interactively, you can select current line with Shift + V, and then do /\%Vsearch (see http://vimdoc.sourceforge.net/htmldoc/pattern.html#/\%V).
try to Find first character of the Pattern by typing
f <letter>
It's not exactly what you need but can help to solve the problem.
/\%9lsearch
Where \%9 means line number 9.
Typing in the line number is still a bit lame. You can ctrl+r= followed by a vim expression and enter to evaluate the vim expression and insert its output. line('.') will return the line of the cursor.
In one complete step
/\%<c-r>=line('.')<cr>lsearch
For more help see:
:h /\%l
:h i_CTRL-R
Place the cursor on the line you want to search in
Select it with shift+v
Type / to begin searching
Prefix your term with \%V, e.g. \%Vabc to search for abc in only the visually selected blocks (in our case the single line)
You can search without replacing by using
:s/PATTERN//gc
Then press n to skip the replacement. If the pattern is not found, you won't even be asked.
You could also just highlight the current line or the range of lines.

Specifying position for a command in Ex mode

I want to remove percentage marks from the following lines:
oh_test_() ->
[
%{"fold", ?_test(fold(ns()))},
%{"fold nested", ?_test(fold_nested(ns()))},
%{"push arg empty table", ?_test(push_arg_empty_table(ns()))},
%{"push arg table 1", ?_test(push_arg_table1(ns()))},
%{"push arg nested table", ?_test(push_arg_nested_table(ns()))},
%{"multicall 0", ?_test(multicall_0(ns()))},
%{"multicall 1", ?_test(multicall_1(ns()))},
%{"multicall 2", ?_test(multicall_2(ns()))}
].
Cursor is on the line with first %.
:,/%/s/%//
Or:
:,/%/normal ^x
Expected: all percent marks removed. Result: removes only first two percent marks.
Why?
How should I do it
Without using visual mode, and
Not counting line numbers?
Question 1:
Your range: ,/%/ is roughly translated starting from the current line. The end of the range will be the next line that matches /%/ after the current cursor line. This will yield the 2 lines. See :h :, for more information.
Question 2:
There are many ways to do accomplish this. You have already presented a normal and a s/// method. One way to fix your commands is to adjust the range. One of the following will work:
,/\]\./-1 match the ending ]. and then subtract a line
,/^\s*%\(.*\n\s*%\)\#!/ Use a negative look ahead to search for a line that does not start with a %.
All together you could use:
:,/\]\./-1s/%//
:,/^\s*%\(.*\n\s*%\)\#!/s/%//
:,/\]\./-1norm ^x
:,/^\s*%\(.*\n\s*%\)\#!/norm ^x
An alternative to using a macro. The nice thing about using macros in this case is that when an error occurs it stops. Basically you record a macro to search for the % and then delete it then move to the next line. Execute this macro a large number of times. When a % cannot be found the macro will stop.
qq0f%xjq999#q
The macro is my preferred method in this case as I do not need to do any crazy patterns or go looking for the end of the block.
If you allowed the use of visual mode I would suggest vi]k:norm ^x
For more information see:
:h range
:h :,
:h /\#!
:h q
:h #q
:h i]
You first example is basically saying... from my current position until the next % issues the command s/%//...
What you may want to do is something like
:,$ s/%//
which says, for each line from my current position till the end of the file ($), issue the command s/%//
If you didn't want to do it till the end of the file then you could
:set number
Which will show you line numbers, then do something like
:2,8 s/%//
which just issues the command for all lines from 2-8
You seem to be using :,/%/ in a way that should use :g/%/. You could use your command as such: :g/%/s/%// or :g/%/norm f%x
See :help :g for more information on the "global" command. This basically executes a command-mode command on lines matching the pattern. Your version, :,/%/ operates from the current line until the match of "%". This removes the first two because the current line has one and you're searching to the line that has one (the next line). You can read more about this in :help :range. A better way to use this option would be to use a search item that's only on the last line. For example, :,/]/s/%// or :,/]/norm f%x.

Resources