4

Given an input string:

<m>1</m>
<m>2</m>
<m>10</m>
<m>11</m>

I would like to replace all values that are not equal to 1 with 5.
So the output String should look like:

<m>1</m>
<m>5</m>
<m>5</m>
<m>5</m>

I tried using:

gsub(/(<m>)([^1])(<\/m>)/, '\15\3')

But this will not replace 10 and 11.

1
  • I have to admit that I'm kind of curious why. Commented Dec 6, 2010 at 14:38

3 Answers 3

21

#gsub can optionally take a block and will replace with the result of that block:

subject.gsub(/\d+/) { |m| m == '1' ? m : '5' }
Sign up to request clarification or add additional context in comments.

3 Comments

what I needed in the end was something like this: gsub(/(<m>)(\d+)(<\/m>)/) { | m1 | m1.gsub(/\d+/) { | m2 | if ['1', '2', '4'].include?(m2) m2 else '5' end } }
If you're using Ruby 1.9 you can use the pattern /(?<=<m>)(\d+)(?=<\/m>)/ to simplify it. The (?<=...) and (?=...) are a lookbehind and a lookahead, and those won't be included in the matched string.
or you can use $1, $2 and $3 in the block and just ignore the parameter: subject.gsub(/(<m>)(\d+)(<\/m>)/) { |m| $1 + ($2 == '1' ? $2 : '5') + $3 }
4

Without regexp just because it's possible

"1 2 10 11".split.map{|n| n=='1' ? n : '5'}.join(' ')

Comments

3
result = subject.gsub(/\b(?!1\b)\d+/, '5')

Explanation:

\b    # match at a word boundary (in this case, at the start of a number)
(?!   # assert that it's not possible to match
 1    # 1
 \b   # if followed by a word boundary (= end of the number)
)     # end of lookahead assertion
\d+   # match any (integer) number

Edit:

If you just wish to replace numbers that are surrounded by <m> and </m> then you can use

result = subject.gsub(/<m>(?!1\b)\d+<\/m>/, '<m>5</m>')

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.