简体   繁体   中英

ruby regex - how replace nth instance of a match in a string

In my app I need to be able to find all number substrings, then scan each one, find the first one that matches a range (such as between 5 and 15) and replace THAT instance with another string "X".

My test string s = "1 foo 100 bar 10 gee 1"

My initial pattern is any string of 1 or more digits, eg, re = Regexp.new(/\\d+/)

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

If I want to replace the Nth match, and only the Nth match, with "X" how do I?

For example if I want to replace the third match "10" (matches[2]) I can't just say s[matches[2]] = "X" because that does two replacements

"1 foo X0 bar X gee 1"

Any help would be appreciated!

String#gsub has a form that takes a block. It yields to the block for each match, and replaces the match with the result of the block. So:

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" 

An alternate way is to construct number range using character class (if it is not too complicated)

>> 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"
  • the negative lookarounds ensure that part of digit sequence are not matched
    • you can use \\b instead of lookarounds if the numbers cannot be part of words like abc12ef or 8foo
  • ([5-9]|1[0-5]) will match numbers from 5 to 15


Initially, the title lead me to think that you want to replace Nth occurrence - for ex: N=2 means replace second occurrence of any digit sequence. For that you can use this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM