0

If I have this line:

a{word}   a{20]   a{word}   a{20]

and type :g/a{.\{-}\]/s/{/\[/gc vi prompts me to change all four occurrences of { to [.

I want it to prompt me to replace only the matches that occur immediately to the right of the cursor after finding a match, i.e., to prompt me to change only the a{20]'s to a[20]'s.

Could somebody explain how to do this please?

  • Why are you currently using a global command? What do you want the command to do on the other lines in the file? – Rich Apr 17 '18 at 11:07
  • The example was too simple. I have many occurrences of the pattern {ab] in the file, where a and be a numbers between 0-9, I want to change each such occurrence to [ab], and ignore the myriad occurrences of {'s that occur on the same lines as the {ab]'s. Unfortunately, @Pak's suggestion below doesn't do the skipping part, i.e., it prompts me for every { that occurs on a line that has an {ab] in it. – Leo Simon Apr 18 '18 at 6:03
  • @LeoSimon I'm glad you found a working solution. I'm curious where my solution didn't work; it should have only tried to replace the { in the second and fourth block in your example. Do you have an example you could provide where it didn't work? – Pak Apr 18 '18 at 17:31
  • I'm embarrassed to say that it was, I think, because I jumped straight to implementing it using :g instead of your :% which was new to me. Yours would have worked just fine, I just took a shortcut. I wanted to accept both answers but it doesn't seem to be an option! – Leo Simon Apr 18 '18 at 23:14
2

You've explained in a comment your requirements:

I have many occurrences of the pattern {ab] in the file, where a and be a numbers between 0-9, I want to change each such occurrence to [ab], and ignore the myriad occurrences of {'s that occur on the same lines as the {ab]'s.

This expression only includes two digits \d between the { and ] characters and ends the match with \ze after the opening { so that the rest of the expression isn't replaced:

%s/{\ze\d\d]/[/gc

If you instead want it to match any number of digits, use a non-greedy repeat \{-}:

%s/{\ze\d\{-}]/[/gc

I can also help explain why what you were trying doesn't work:

The :global command simply runs the following command on all the matching lines. It doesn't specifically place the cursor at the position of the match. If you must, it's better to imagine it placing it at the start of the line, because that's how :g//normal works, (e.g. Try something like :g/a/norm f1x and see that it deletes the first 1 character after the first character on the line: not the first after an a character,) but see :help :global for an explanation of how the command actually functions.

And regardless of the above, the substitute command ignores cursor position anyway. If you use the g flag, it acts on all matches on the line, and if you omit it, it acts only on the first match on the line.

  • Spectacular, thanks to both of you for the very helpful explanations – Leo Simon Apr 18 '18 at 13:15
  • I've tried to modify your suggestion to change {dd] to {dd} i.e., change the closing delimiter rather than the opening one, but am unable to make this seemingly simple change. My guess is that it requires some analog of \ze, and that you can't do it with \ze. Would you mind adding this to your explanation please? – Leo Simon Apr 18 '18 at 13:53
  • @LeoSimon Your guess is correct. The e in \ze stands for end. Try this: :%s/{\d\d\zs]/}/gc – Rich Apr 18 '18 at 14:01
2

I think rather than trying to base things on the current cursor position, you'd be better off formulating your search pattern to be more specific to what you're looking for. From what I can tell, you're trying to replace the { before a number that's followed by a ]. I would do something like this:

:%s/{\ze\d\+\]/[/gc

The :g command wasn't really necessary, so I combined it into just a substitute command. This first searches for a {, followed by one or more digits followed by a ]. The \ze after the { sets the end of the search pattern. This makes it so that only the stuff before it (in this case, the {) gets replaced by the replacement part, which is simply a [.

  • Thanks for the suggestion @Pak, please see my comment to Rich above – Leo Simon Apr 18 '18 at 6:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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