Есть ли Ruby способ заменить последние четыре цифры строки, исключая пробелы? - PullRequest
0 голосов
/ 19 января 2020

Мне нужно найти способ анонимизировать последние четыре цифровых символа. Представленная строка телефонного номера, например "+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 ")

Ответы [ 3 ]

3 голосов
/ 19 января 2020

Вы можете использовать

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

См. regex demo и online Ruby demo .

Подробности

  • \d - ди git ...
  • (?=(?:\D*\d){0,3}\D*\z) - за которым сразу следует
    • (?:\D*\d){0,3} - от 0 до 3 последовательных вхождения
      • \D* - 0+ non-di git char
      • \d - di git
    • \D* - 0+ non-di git char
    • \z - конец строки ($ соответствует концу строки в Ruby регулярном выражении).

Другая идея: сопоставьте последние четыре цифры с любыми символами, кроме цифр, а затем замените только эти цифры на X:

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

См. this Ruby demo

Здесь (?:\d\D*){4}\z соответствует четырем последовательным вхождениям di git и любых 0+ не-di git символов в конце строки и $~[0] в * Блок 1052 * представляет все значение совпадения, где .gsub(/\d/, 'X') заменяет каждый ди git на X.

0 голосов
/ 20 января 2020

Вы можете перевернуть строку, а затем заменить один ди git на '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' в зависимости от предпочтения.

0 голосов
/ 19 января 2020

Если ваша строка содержит только номер телефона, который заканчивается на 'dd dd', где d - это ди git, вам не нужно регулярное выражение:

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

Я полагаю Однако тем интереснее интерпретация «последних четырех числовых символов», что последовательные пары цифр могут быть разделены нулем или несколькими нецифрами. В этом случае следующий простой способ сделать нужные замены:

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
...