是否有 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') }
这里,(?:\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'
。
我必须想办法匿名化最后四个数字字符。呈现 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') }
这里,(?:\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'
。