1

The following search command will make a range and search/replace within it. Specifically, it looks for 'first' in the text, then stops when it finds 'second' across multiple lines. Then, within that range of selected things, it will replace foo with bar. What I'm not sure how to do is to replace all occurrences of foo on each line with bar. I've tried using /%s/ instead of /s/ What am I missing?

:/first/;/second/s/foo/bar
6
  • 3
    not sure I understand, but don't you just need the g flag? Oct 24, 2018 at 8:36
  • 1
    I think the syntax you're looking for is :%s/foo/bar (or with the g flag to replace all of the occurrences)
    – statox
    Oct 24, 2018 at 8:43
  • Nope %s doesn't work.
    – cmaughan
    Oct 25, 2018 at 14:39
  • Note: One way to achieve the above would be to keep running the command until all cases of foo on the same line were replaced.....
    – cmaughan
    Oct 25, 2018 at 14:40
  • I would suggest to emphasize part of the phrase "to replace all occurrences of foo on each line with bar"
    – Maxim Kim
    Oct 25, 2018 at 15:34

2 Answers 2

2

UPDATE

So I have found simpler solution:

:/first/,/second/g/bar/s/foo/bar/g
  1. /first/,/second/ take a range between first and second
  2. g/bar/ filter out lines that do not have bar (keep lines that has bars)
  3. s/foo/bar/g substitute all foos with bars within filtered lines.

Old solution

It is kind of tricky and probably would be much easier if :g command could be used recursively with the ranges. But it can't.

You can try the following:

:/first/,/second/s/\(bar.*\zsfoo\ze\)\|\(\zsfoo\ze .*bar\)/bar/g
  1. range from first to second
  2. substitute foos only if the line has bar before foo or after foo

I have tested it with the following:

foo bar foo bar bar

first
foo bar foo bar bar
hello foo foo world
hello foo hlkj sdklfj bar fooworld
foo bar foo bar bar
foo bar foo bar bar
second

foo bar foo bar bar
foo bar foo bar bar
foo bar foo bar bar

After the substitution:

foo bar foo bar bar

first
bar bar bar bar bar
hello foo foo world
hello bar hlkj sdklfj bar barworld
bar bar bar bar bar
bar bar bar bar bar
second

foo bar foo bar bar
foo bar foo bar bar
foo bar foo bar bar
5
  • That's a pretty nasty solution! But it's a solution none the less.... ;) I was hoping for something simpler....
    – cmaughan
    Oct 25, 2018 at 14:38
  • @cmaughan I’m confused. You comment under my answer that you want every foo replaced with bar, but this is not what this answer does (or is intended to do). Could you clarify exactly what you mean? Perhaps with a before and after of an example file?
    – Rich
    Oct 25, 2018 at 15:01
  • @cmaughan check the updated version of the answer -- it is way simpler
    – Maxim Kim
    Oct 25, 2018 at 15:31
  • @MaximKim Your simpler solution does the right thing, though I think your afterwards substitution has 2 'foo' in it that are also correctly changed using your approach; I get all foo's between first and second converted to 'bar', which is what I wanted :)
    – cmaughan
    Oct 25, 2018 at 15:37
  • 1
    @cmaughan the thing is -- you question is very hard to understand. Basically I can read it the way the answer :/first/,/second/s/foo/bar/g will be correct. It will replace all foos with bars on each line between first and second. My current answer on the other hand works slightly different. It does replacement between said range but only on lines that have bars.
    – Maxim Kim
    Oct 25, 2018 at 15:44
0

As @ChristianBrabandt mentioned in a comment, you need to use the g flag to the :substitute command:

:/first/;/second/s/foo/bar/g

See :h :s_flags for details on this and other flags you can use with :s commands.

5
  • He wants: > to replace all occurrences of foo on each line with bar
    – Maxim Kim
    Oct 24, 2018 at 13:53
  • 1
    @MaximKim Yes. You’re reading that as meaning they only want the replacements to occur on lines that contain the text bar. I think what the OP actually means is that they want every foo replaced with bar (on every line).
    – Rich
    Oct 24, 2018 at 19:31
  • Yes, that's right - every foo with bar on every line. s/ (and %s/) don't do this. And adding g doesn't either.
    – cmaughan
    Oct 25, 2018 at 14:37
  • @cmaughan That’s odd. It works in my testing. Could you give an example of a file where it doesn’t work for you?
    – Rich
    Oct 25, 2018 at 14:59
  • Now I read the question once again and a little bit confused.
    – Maxim Kim
    Oct 25, 2018 at 15:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.