Reputation: 12356
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?
Upvotes: 12
Views: 4443
Reputation: 45087
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
.
\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.
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
Upvotes: 8
Reputation: 22674
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.
Upvotes: 14