4

Is there a way to substitute a pattern only if it occurs inside the brace pair that the cursor is on?

For instance, if I have the text

int bar()
  {
  ...
  }

int foo()
  {
  char bar;

  bar = 'a';
  }

I can change all instances of bar to baz in the second brace pair using line numbers, e.g. :7,11s/bar/baz/g. Is it possible to do this without the line numbers, only having the cursor on one of the braces?

Edit:

The version of Vi I have is 3.10, which doesn't appear to have visual mode

1 Answer 1

8

First Solution


This requires some advanced cmdline-range magic to work. Here is what I have come up with:

:?{?,/}/s=bar=baz=g

Now, to break it down:

  • ?{? - Searches backwards for the first line containing a {. You can use any regex in the place of { if you need to match more specific cases.
  • , - This takes the lines in front of and in back of it, and matches all lines in between.
  • /}/ - Searches forwards for the first line containing a }. Once again, this could be any regex to match your specific needs.
  • s=bar=baz=g - This is just a normal search and replace statement, using = as the seperator.

Note that you must have the cursor between the two parentheses, otherwise it will not work. These two help pages are very useful on the subject of cmdline-ranges:

:help 10.3
:help cmdline-ranges

Second Solution


There is also a slightly simpler way of doing it as well. These are the keys you have to press:

vi{:s/bar/baz/g

Here is how this works:

  • vi{ - Visually select an "inner block". See :help text-objects for more on this.
  • : - Key to start a command as usual, however when in visual select mode, vim automatically inserts markers for the beginning and ending of the selection. Like so: :'<,'> This is more special cmdline-range syntax, where ' means the line at marker <, which in this case is the marker which is always set to the beginning of the visual selection.
  • s/bar/baz/g - Normal substitution command.
3
  • The first solution works great. The second solution didn't work for me, probably because the version of vi I am using is 3.10
    – horns
    Mar 27, 2015 at 2:42
  • After using the first solution here some, I realized that it flops when there are inner pairs of brackets.
    – horns
    Mar 27, 2015 at 19:28
  • Indeed it does. It is a very simple solution, so I figured there would be some disadvantage to it. I'll see what I can do to make it work, but it might end up being extremely complex. Mar 27, 2015 at 19:32

Your Answer

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

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