2

I have something like the following text

( parens ) ( 1 + growth )   (1+growth)   (1 +growth) ( parens )

and I'd like replace every instance of ( 1 + growth ), regardless of whitespace, with say, growthFun

The nongreedy search command

:g/(.\{-}1.\{-}+.\{-}growth.\{-})/s//growthFun/gc

almost works, i.e., it locates the second and third instances, but the first time around it grabs ( parens ) ( 1 + growth )

This is puzzling since it does not do the same thing at the end of the line, i.e., it does not grab (1 +growth) ( parens ) the third time around. Could somebody please explain why the difference, and then how to avoid the first incorrect grab?

A closely related question is: the nongreedy construction .\{-} must be the most horrible, unnatural things the vi inventors every invented. Is there a way to alias it in .vimrc so that, for example, typing

:g/( ;ng 1 ;ng etc )

would expand to

:g/( .\{-} 1 .\{-} etc )

Thanks for any advice!

1
  • 2
    If I replace .\{-} with \s\{-} or [^()], the command looks like it works according to your requirement. Would that be acceptable (look just for a space(s) or non-parenthesis in lieu of non-newline characters? Jan 11, 2018 at 22:50

2 Answers 2

4

Rather than searching for as few of any character as possible, change it to search for as many white space characters as possible. This can be done by replacing .\{-} with \s*.

I would simplify (at least I think it's simpler) further with this:

:%s/(\s*1\s*+\s*growth\s*)/growthFun/gc

Also, take a look at :help character-classes. There are a lot of really useful character classes that can be used to match only certain types of characters, such as only digits or only lower case letters.

Edit: It occurs to me that I didn't necessarily answer your questions.

The reason you are seeing a difference in behavior is because the end of your pattern is growth.\{-}) and \{-} finds 0 or more of the previous atom, but as few as possible. So, this is basically saying "Find growth, then find a ) and do it in as few characters as you can". Since there is a ) immediately after the last growth, it doesn't have to go very far.

On the other hand, the beginning of your pattern is (.\{-}1 which similarly says "Find a ( and a 1 and do it in as few characters as you can". Since a 1 doesn't appear within the first group of parentheses, it has to continue until the second group.

I'm not aware of any way to alias the .\{-}. I also found this syntax rather awkward at first, but it seems to make a bit more sense when you realize that you can use numbers inside the curly braces to specify exactly how many to match (or even a range of how many to match). For example, you can do \{6} to find exactly 6 of the previous atom or \{2,6} to find 2 to 6 of them. Adding a - such as \{-6} means to find up to 6, but as few as possible. Leave out the number (i.e. \{-}) and you're just saying "find as few as possible". :help pattern-multi-items has a bunch more information about this.

2
  • Thanks to all three responses. I accepted @Pak 's response because \s* is so much easier to type than \s.\{-} and for the explanation !
    – Leo Simon
    Jan 13, 2018 at 0:16
  • Glad I could help!
    – Pak
    Jan 15, 2018 at 4:38
5

Replace non-new line character with the space character or non-parenthesis

If we examine the start of your match expression, (.\{-}1, we see that we can find a quick match which finds the minimum number of non-newline characters until the first 1.

Here are the results of this match, /(.\{-}1:

(.{-}1

This behavior you are seeing is expected behavior.


I like the idea of going after a space character, \s, or a non-parenthesis character class for our atom which we are trying to find a non-greedy match:

:g/(\s\{-}1\s\{-}+\s\{-}growth\s\{-})/s//growthFun/gc

Here are the results:

enter image description here

Here is my non-parenthesis character class command:

:g/([^()]\{-}1[^()]\{-}+[^()]\{-}growth[^()]\{-})/s//growthFun/gc

Here are the results for non-parenthesis character class:

enter image description here

With your second question, I personally like the syntax for quantifiers. Perhaps someone else has some ideas on this.

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.