68

I want to do this:

%s/shop_(*)/shop_\1 wp_\1/

Why doesn't shop_(*) match anything?

3
  • I'm a little closer: %s/shop_/& wp_\1 Commented Jul 26, 2010 at 21:22
  • 1
    If I didn't understand correctly, try adding examples. Commented Jul 26, 2010 at 21:25
  • 7
    This question would be more useful to future SO users if an example was added of what is being attempted with the regex. Commented Apr 22, 2014 at 17:05

4 Answers 4

80

There's several issues here.

  1. parens in vim regexen are not for capturing -- you need to use \( \) for captures.

  2. * doesn't mean what you think. It means "0 or more of the previous", so your regex means "a string that contains shop_ followed by 0+ ( and then a literal ).
    You're looking for ., which in regex means "any character". Put together with a star as .* it means "0 or more of any character". You probably want at least one character, so use .\+ (+ means "1 or more of the previous")

Use this: %s/shop_\(.\+\)/shop_\1 wp_\1/.

Optionally end it with g after the final slash to replace for all instances on one line rather than just the first.

Sign up to request clarification or add additional context in comments.

2 Comments

Just a nit: the existing regex didn't search for a literal *), just a literal ).
So basically Vim wants reverse escaping: escape all regex syntax (e.g. \(re\)\?move to match both 'move' and 'remove') instead of escaping anything that should be taken literally.
33

If I understand correctly, you want %s/shop_\(.*\)/shop_\1 wp_\1/

Escape the capturing parenthesis and use .* to match any number of any character.

(Your search is searching for "shop_" followed by any number of opening parentheses followed by a closing parenthesis)

Comments

3

If you would like to avoid having to escape the capture parentheses and make the regex pattern syntax closer to other implementations (e.g. PCRE), add \v (very magic!) at the start of your pattern (see :help \magic for more info):

:%s/\vshop_(*)/shop_\1 wp_\1/

Comments

1

@Luc if you look here: regex-info, you'll see that vim is behaving correctly. Here's a parallel from sed:

echo "123abc456" | sed 's#^([0-9]*)([abc]*)([456]*)#\3\2\1#'
sed: -e expression #1, char 35: invalid reference \3 on 's' command's RHS

whereas with the "escaped" parentheses, it works:

echo "123abc456" | sed 's#^\([0-9]*\)\([abc]*\)\([456]*\)#\3\2\1#'
456abc123

I hate to see vim maligned - especially when it's behaving correctly.

PS I tried to add this as a comment, but just couldn't get the formatting right.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.