6

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

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

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

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

如果我想用“X”替换第 N 个匹配项,并且只有第 N 个匹配项,我该怎么办?

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

"1 foo X0 bar X gee 1"

任何帮助,将不胜感激!

4

2 回答 2

8

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" 
于 2012-09-21T04:15:31.560 回答
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"
  • 消极的环顾四周确保数字序列的一部分不匹配
    • 如果\b数字不能是诸如abc12ef8foo
  • ([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"
于 2018-09-25T14:54:26.300 回答