I'm learning how substitution works in Vim. And I find this example really weird to understand: :?a?,/b/s/bad/good. I know what this command will do in general. But why use two question marks to wrap a? What does it mean?
- 247
- 1
- 5
1 Answers
The command is composed of two parts:
:?a?,/b/ The range
s/bad/good The substitution command
You probably already know that the :s command can take a range:
:s/bad/goodwill do the substitution on the current line:%s/bad/goodwill do the substitution on all the lines of the buffer- And
/pattern1/,/pattern2/s/bad/goodwill perfom the substitution between the next line matchingpattern1and the next one matchingpattern2.
The help :h :range gives us the different items we can use as a range:
Line numbers may be specified with: *:range* *{address}*
{number} an absolute line number
. the current line *:.*
$ the last line in the file *:$*
% equal to 1,$ (the entire file) *:%*
't position of mark t (lowercase) *:'*
'T position of mark T (uppercase); when the mark is in
another file it cannot be used in a range
/{pattern}[/] the next line where {pattern} matches *:/*
?{pattern}[?] the previous line where {pattern} matches *:?*
\/ the next line where the previously used search
pattern matches
\? the previous line where the previously used search
pattern matches
\& the next line where the previously used substitute
pattern matches
Take a particular note of ?{pattern}[?] the previous line where {pattern} matches: this is what is used in your question.
Your command :?a?,/b/s/bad/good will be applied to the lines between the previous line matching a and the next one matching b. To make the difference clear between // and ?? here are two examples:
Take this file:
a
bad
b
bad
a
With you cursor on b in line 3 if you use :?^a$?,/^b$/s/bad/good you will get:
a
good
b
bad
a
Because line 1 is the previous one matching ?^a$? and line 3 is the next one matching /^b$/
Now if you use :/^a$/,/^b$/s/bad/good you will get
a
bad
b
good
a
Because the next line matching /^a$/ is line 5 and Vim know how to reverse the inverted ranges.
Note that in the range part of the command changing // to ?? changes how the action behave. This is different than changing the / characters in the substitution part of the command where s/bad/good/, s?bad?good? and s;bad;good are all equivalent as explained in this question.
- 49,782
- 19
- 148
- 225
?are in the range section of the command and if I understand:h :rangeproperly they reference to?{pattern}[?] the previous line where {pattern} matcheswhich is not the same thing as what I asked in the question you linked. – statox Jul 28 '20 at 11:49