是否有 Ruby 方法来替换字符串的最后四位数字,不包括空格?

is there a Ruby way to substitute the last four digits of a string, excluding spaces?

我必须想办法匿名化最后四个数字字符。呈现 phone 数字字符串,如“+36 6 41 88 75 22”(或任何其他格式,如“+36641887522”或 +36 6 418 875 22 等等),我希望我的代码输出“ +36 6 41 88 XX XX".

phoneNumber = "+36 6 41 88 75 22" 我找到的最接近我想要的选择的正则表达式是: /\d.{4}$/ 这很方便,因为 lastFour = phone.scan(/\d.{4}$/).join 等于“75 22”,包括 space.

现在我想用 "X" 替换所有数字(不是 space!),但是

phoneNumber.gsub(/\d.{4}$/, "X")

输出“+36 6 41 88 X”,我希望我的代码输出“+36 6 41 88 XX XX”。

我也尝试过以下繁琐的解决方案:

phoneNumber = "+36 6 41 88 75 22"
def anonymizer(phone)
    lastFour = phone.scan(/\d.{4}$/).join
    anonFour = lastFour.chars
    anonFour.each do |digit|
        digit.gsub(/[0-9]/, "X")
    end
    puts "attempted transform #{anonFour}"
    phone.gsub(lastFour, anonFour.join)
end


phoneyNumber = anonymizer(phoneNumber)
puts phoneyNumber 

无济于事,因为它returns原样的数字(“+36 6 41 88 75 22”而不是“+36 6 41 88 XX XX”)

您可以使用

phoneNumber = phoneNumber.gsub(/\d(?=(?:\D*\d){0,3}\D*\z)/, 'X')

参见regex demo and the online Ruby demo

详情

  • \d - 一个数字...
  • (?=(?:\D*\d){0,3}\D*\z) - 紧随其后的是
    • (?:\D*\d){0,3} - 0 到 3 次连续出现
      • \D* - 0+ 个非数字字符
      • \d - 一个数字
    • \D* - 0+ 个非数字字符
    • \z - 字符串结尾($ 匹配 Ruby 正则表达式中的一行结尾)。

另一个想法:将最后四位数字与数字以外的任何字符匹配,然后仅将这些数字替换为 X:

phoneNumber.gsub(/(?:\d\D*){4}\z/) { $~[0].gsub(/\d/, 'X') }

this Ruby demo

这里,(?:\d\D*){4}\z匹配字符串末尾连续出现的4个数字和任何0+个非数字字符,gsub块中的$~[0]表示.gsub(/\d/, 'X') 将每个数字替换为 X.

的完整匹配值

如果您的字符串仅包含以 'dd dd' 结尾的 phone 数字,其中 d 是一个数字,则您不需要正则表达式:

'+36 6 41 88 75 22'[0..-6] + 'XX XX'
  #=> "+36 6 41 88 XX XX" 

不过,我假设 "last four numerical characters" 的更有趣的解释是连续的数字对可以分隔为零个或多个非数字。在这种情况下,以下是进行所需替换的简单方法。

def sub_last4(str)
  n = str.count('0-9')
  str.gsub(/\d/) { |s| (n -= 1) <= 3 ? 'X' : s }
end

sub_last4 '+36 6 41 88 75 22'
  #=> "+36 6 41 88 XX XX" 
sub_last4 '+36 6 41 88 7522'
  #=> "+36 6 41 88 XXXX"
sub_last4 '+36 6 how 41 8 now 8 75 2 brown 5 cow'
  #=> "+36 6 how 41 8 now 8 XX X brown X cow"
sub_last4 'SY-0-6447'
  #=> "SY-0-XXXX"

这是第二种方法。

def sub_last4(str)
  4.times.each_with_object(str.dup) { |_,s|
    s[s.rindex(/\d/)] = 'X' }
end

您可以反转字符串,然后用 'X' 替换单个数字四次。

phone_number = '+36 6 41 88 75 22'

phone_number.reverse!
4.times { phone_number.sub!(/\d/, 'X') }
phone_number.reverse!

phone_number
#=> "+36 6 41 88 XX XX"

请注意,我在这里使用了变异方法,如果您不想改变原来的方法,请将第一个 phone_number.reverse! 替换为 phone_number = phone_number.reverse。这将创建一个新的字符串,其他变异方法可以安全地对其进行操作。

您可以根据偏好将 phone_number.sub!(/\d/, 'X') 替换为 phone_number[/\d/] = 'X'