我必须找到一种使后四个数字字符匿名的方法。出现一个电话号码字符串,例如“ +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”(包括空格)。
现在我想用“ X”代替所有数字(而不是空格!),但是
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
无济于事,因为它按原样返回数字(“ +36 6 41 88 75 22”而不是“ +36 6 41 88 XX XX”)]
如果您的字符串仅包含以'dd dd'结尾的电话号码,其中d
是数字,则不需要正则表达式:
'+36 6 41 88 75 22'[0..-6] + 'XX XX'
#=> "+36 6 41 88 XX XX"
但是,我认为对“最后四个数字字符”的解释更有趣,可以将连续的数字对分隔为零个或多个非数字。在这种情况下,以下是进行所需替换的简单方法。
def sub_last4(str)
n = str.count('0123456789')
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
您可以使用
phoneNumber = phoneNumber.gsub(/\d(?=(?:\D*\d){0,3}\D*\z)/, 'X')
请参见regex demo和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
匹配四个连续出现的数字和字符串末尾的任何0+个非数字字符,并且$~[0]
块中的gsub
表示整个匹配值,其中.gsub(/\d/, 'X')
替换每个X
的数字。
您几乎可以用自己的正则表达式\d.{4}$
来获得它,但只需要进行两个小修改。
由于您想一次匹配一位数字并用X
代替,因此您需要使用前瞻性(因为这不会消耗字符),因此一次一次只需要使用\d
匹配一位数字即可。并将其更改为\d(?=.{4}$)
。
下一次,因为您要匹配最后四位数字,因此需要将{4}
更改为{0,4}
,以便您的前瞻性说,匹配行尾之前有零到四个字符的数字。
并且具有这两个修改的新正则表达式将紧随其后,
\d(?=.{0,4}$)
将为您提供所需的结果。