ruby regex - 如何在字符串中替换匹配的第n个实例

时间:2012-09-21 04:11:23

标签: ruby regex

在我的应用程序中,我需要能够找到所有数字子串,然后扫描每个子串,找到匹配范围的第一个(例如5到15之间)并用另一个字符串“X”替换THAT实例。 / p>

我的测试字符串s = "1 foo 100 bar 10 gee 1"

我的初始模式是1位或更多位的任何字符串,例如re = Regexp.new(/\d+/)

matches = s.scan(re)提供["1", "100", "10", "1"]

如果我想替换第N场比赛,只有第N场比赛,用“X”代替我?

例如,如果我想替换第三场比赛“10”(匹配[2]),我不能只说 s[matches[2]] = "X"因为这会做两次替换

"1 foo X0 bar X gee 1"

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:7)

String#gsub有一个表格,需要一个块。它为每个匹配产生块,并将匹配替换为块的结果。所以:

first = true
"1 foo 100 bar 10 gee 1 12".gsub(/\d+/) do |digits|
  number = digits.to_i
  if number >= 5 && number <= 15 && first
    # do the replacement
    first = false
    'X'
  else
    # don't replace; i.e. replace with itself
    digits
  end
end
# => "1 foo 100 bar X gee 1 12" 

答案 1 :(得分:1)

另一种方法是使用字符类构造数字范围(如果不太复杂的话)

>> s = "1 foo 100 bar 10 gee 1"
=> "1 foo 100 bar 10 gee 1"
>> s.sub(/(?<!\d)([5-9]|1[0-5])(?!\d)/, 'X')
=> "1 foo 100 bar X gee 1"
  • 否定性回望确保部分数字序列不匹配
    • 如果数字不能为\babc12ef之类的单词的一部分,则可以使用8foo代替环顾四周
  • ([5-9]|1[0-5])将匹配5到15之间的数字


最初,标题使我认为您想替换第N个出现的字符-例如:N = 2表示替换任何数字序列的第二个出现的字符。为此,您可以使用:

# here the number inside {} will be N-1
>> s.sub(/(\d+.*?){1}\K\d+/, 'X')
=> "1 foo X bar 10 gee 1"