How to do substitution only on highlighted text in vim? - vim

Before doing substitution, I usually type /foo to search the pattern first.
Vim automatically highlight all strings match the pattern.
Then I figure out how to write the substitution command :%s/foo/bar/g.
When the pattern is complex, it's much harder to write the substitution command than the search command.
If I can do substitution only on highlighted strings. It becomes easy.
For example:
Question: Translate Part of a Line
I can figure out the search pattern: /\[\[\(http\)\#!.\{-}\]\]
But I cannot figure out the substitution command easily.

You can replace the previously searched pattern if you use an empty string as the search pattern in the substitute command:
After /foo type :%s//bar/g in normal mode to replace "foo" by "bar".

You could use the 'c' flag to tell Vim to confirm before replacing. It highlights and stops to ask before every match it finds to the given pattern.
:%s/foo/bar/gc

I just figured out:
:%s##\=substitute(submatch(0), '_', '/', '')#g
But is there any better ways?

Related

Can not find the good syntax for a vim sustitute pattern

I have a bunch of t_ prefixed fonction names in a header file and i would like to remove this prefix from some of them.
I have ended by typing :
:s/\(\s+\)t_\([^(]+\)(/\1\2(/c
But vim complains with Pattern not found
What is wrong in my pattern ?
You forgot to put a backslash before + to give it its quantifier meaning. You can also probably simplify it using \< to match the start of a word instead of capturing spaces.
I suggest breaking the problem down, first the search:
/\v\s+\zst_\ze.*\(
Now the substitution:
:s///\c
We can reuse a search pattern simply typing an empty search on the substitution
OBS: I suppose your functions have () at the end of the line, so .*().
Another thing; \zs and \ze to match only t_, for more see: :h \zs.
If you are using neovim you can see what happens befor hitting enter, just put these lines on your init.vim:
if has("nvim")
set inccommand=nosplit
endif

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

Find and replace only part of a single line in Vim

Most substitution commands in vim perform an action on a full line or a set of lines, but I would like to only do this on part of a line (either from the cursor to end of the line or between set marks).
example
this_is_a_sentence_that_has_underscores = this_is_a_sentence_that_should_not_have_underscores
into
this_is_a_sentence_that_has_underscores = this is a sentence that should not have underscores
This task is very easy to do for the whole line :s/_/ /g, but seems to be much more difficult to only perform the replacement for anything after the =.
Can :substitution perform an action on half of a line?
Two solutions I can think of.
Option one, use the before/after column match atoms \%>123c and \%<456c.
In your example, the following command substitutes underscores only in the second word, between columns 42 and 94:
:s/\%>42c_\%<94c/ /g
Option two, use the Visual area match atom \%V.
In your example, Visual-select the second long word, leave Visual mode, then execute the following substitution:
:s/\%V_/ /g
These regular expression atoms are documented at :h /\%c and :h /\%V respectively.
Look-around
There is a big clue your post already:
only perform the replacement for anything after the =.
This often means using a positive look-behind, \#<=.
:%s/\(=.*\)\#<=_/ /g
This means match all _ that are after the following pattern =.*. Since all look-arounds (look-aheads and look-behinds) are zero width they do not take up space in the match and the replacement is simple.
Note: This is equivalent to (?<=...) in perl speak. See :h perl-patterns.
What about \zs?
\zs will set the start of a match at a certain point. On the face this sounds exactly what is needed. However \zs will not work correctly as it matches the pattern before the \zs first then the following pattern. This means there will only be one match. Look-behinds on the other hand match the part after \#<= then "look behind" to make sure the match is valid which makes it great for multiple replacement scenario.
It should be noted that if you can use \zs not only is it easy to type but it is also more efficient.
Note: \zs is like \K in perl speak.
More ways?!?
As #glts mentioned you can use other zero-width atoms to basically "anchor" your pattern. A list of a few common ways:
\%>a - after the 'a mark
\%V - match inside the visual area
\%>42c - match after column 42
The possible downside of using one of these methods they need you to set marks or count columns. There is nothing wrong with this but it means the substitution will maybe affected by side-effects so repeating the substitution may not work correctly.
For more help see:
:h /\#<=
:h /zero-width
:h perl-patterns
:h /\zs

VIM how to substitute with offset

The search command in vim allows you to place the cursor relative to the search results. For example, /hello/b+2 places the cursor on the first l.
How do I do that with the substitute command?
s/hello/b+2/_/
does not work.
I need this to replace not the entire search string, but a portion of it only (specifically, to blank out all but the first character of a word).
You generally have two options: similar to other regex engines zero-width matches (though with different syntax):
:s/\(he\)\#<=llo/_/
or vim-specific “set the start of the match here”:
:s/he\zsllo/_/
. Also, there is a workaround which will look similar in almost every other regex engine:
:s/\(he\)llo/\1_/
: this captures text that should be unchanged and makes replacement include it.

Use a register value as search pattern

I wish to use the content of a register as search pattern in Vim.
I would like to do this from the command line so I cannot use the <c-r> syntax since that assumes an interactive session.
It is possible to use a register as a replace pattern, like this
:%s/foo/\=#a/g
However using this syntax as a search pattern does not work
:%s/\=#a/foo/g
it outputs
E64: \= follows nothing
E476: Invalid command
In a pattern (not the replacement part), \= stands for “0 or 1 time” (it is a synonym for \? put should be preferred over \? since the latter means a literal ? when looking backwards.
See :help /\= and help pattern for more details.
Why not :
let #/=#a
%s//foo/g
I don't think it's possible directly, but you can use :exe to achieve this:
:exe '%s/' . #a . '/foo/g'
You can do this with the / register
This doesn't solve the general problem, but it appears to me that the / register is special in this regard: if you leave the search term blank, it will use whatever is in the / register; namely, whatever you searched for last.
So if you want to replace foo with the contents of #a, you could do this:
Search for foo
%s//\=#a/g (or highlight some text and start typing :s to substitute only in that range)

Resources