2

I am trying to write a regular expression in vi to match any whitespace character followed by any digit. Then, at each match, insert a dollar sign between the whitespace and the digit. Here is an example:

A1234 12 14 B1234
B1256 A2 14 C1245
C1234 34 D1 1234K

The correct regex would produce this:

A1234 $12 $14 B1234
B1256 A2 14 C1245
C1234 $34 D1 $1234K

I realize I need to use a back reference, but I can't quite seem to write the correct regex. Here is my attempt:

:'<,'>/(\s\d)/\s\1\$/g

Also, I have Vim's default regex mode turned off (vnoremap / /\v).

Thanks for the help.

1
  • 3
    Why the number 14 in the second line of the correct result example is not prepended with $? Commented Sep 23, 2011 at 1:34

5 Answers 5

10

You need to escape the parentheses to make them work as groupings rather than as actual matches in the text, and not escape the $. Like so:

:%s/\(\s\)\(\d\)/\1$\2/g

This worked for me in vim (using standard magic setting).

Edit: just realized that your non-standard regex settings cause you having the escape 'the other way around'. But still, the trick, I think, is to use two groups. With your settings, this should work:

:%s/(\s)(\d)/\1$\2/g
Sign up to request clarification or add additional context in comments.

1 Comment

There is no need to escape $ sign in the replacement part of the :substitute command even in "magic" mode.
6

Using a back reference is not inevitable. One can make a pattern to match zero-width text between a whitespace character and a digit, and replace that empty interval with $ sign.

:'<,'>s/\s\zs\ze\d/$/g

(See :help /\zs and :help /\ze for details about the atoms changing the borders of a match.)

3 Comments

@sidyll: "Correct"? Is there some standards document I have missed?
Sorry @Johnsyweb, I didn't want to sound this bad. Not because it's documented, but because this one is much cleaner by using features mostly seen in Vim only (\ze and \zs).
@sidyll: Thanks, I feel the same way! Sometimes people value trickery more than elegance, though. (Like here or in that question.)
2

My first thought is:

:%s/(\b\d)/$\1/g

with \b is for word boundary. But it turns out that \b doesn't mean word boundary in Vim regex, rather \< and \> for the start and end of the word. So the right answer would be:

:%s/\(\<\d\)/$\1/g

(Making sure to escape the capturing parenthesis.)

Sorry that my correction came so late.

8 Comments

I'm trying to do the substitution on a visual block, so I did :'<,'>s/(\s\d)/$\1/g, but it didn't work. I get a Pattern not found error with either \b or \s.
Sorry, I don't have opportunity to test it where I am, I'll look into it later.
IIRC \b is backspace, not word boundary.
Hmm ... it is word boundary for sed regex, but not for Vim, apparantly.
'the great thing about standards...'
|
0

Not sure abt the exact vim syntax, but regEx syntax should be this:

search expr - "(\s)([\d])"
replacement expr - "\1 $\2"

so something like:

/(\s)([\d])/\1 $\2/g

Comments

0

This will do the job for you (without using groups):

:%s/\s\@<=\d\@=/$/g

Explanation:

  • %: On every line...
  • s: Substitute...
  • /: Start of pattern
  • \s: Whitespace
  • \@<=: Match behind (zero-width)
  • \d: Digit
  • \@=: Require match (zero-width)
  • /: End of pattern, start of replacement
  • $: What you asked for!
  • /: End of replacement
  • g: Replace all occurrences in the line.

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.