Ruby:子匹配组在不应该的时候是零

Gui*_*rme 0 ruby regex gsub

我正在尝试获取信用卡号码字符串并用星号掩盖中间数字.我使用正则表达式/^([\d]{6})([\d]{3,6})([\d]{4})$/匹配三组:

  • 前6位数
  • 中间数字(3到6)将被混淆
  • 最后4位数

正如您在下面的控制台中看到的那样,首先gsub是匹配组nil,直到我在替换属性中使用文字字符串.然后,当我尝试运行初始调用时,它可以工作.

2.0.0-p598 :001 > c = "5454545454545454"
 => "5454545454545454"

2.0.0-p598 :002 > c.gsub(/^([\d]{6})([\d]{3,6})([\d]{4})$/, $1 + '*' * $2.size + $3)
NoMethodError: undefined method `size' for nil:NilClass
    from (irb):2
    from /Users/guilherme/.rvm/rubies/ruby-2.0.0-p598/bin/irb:12:in `<main>'

2.0.0-p598 :003 > c.gsub(/^([\d]{6})([\d]{3,6})([\d]{4})$/, "anything")
 => "anything"

2.0.0-p598 :004 > c.gsub(/^([\d]{6})([\d]{3,6})([\d]{4})$/, $1 + '*' * $2.size + $3)
 => "545454******5454"
Run Code Online (Sandbox Code Playgroud)

为什么会这样?这是一个错误吗?如何解决这个问题并使其在第一次尝试中起作用?

Ser*_*sev 5

对于更高级的替换,例如这个,你应该使用块形式gsub.魔术变量有值.

s = '1234567890123456'
rgx = /^([\d]{6})([\d]{3,6})([\d]{4})$/

s2 = s.gsub(rgx) do
  $1 + '*' * $2.size + $3
end

s2 # => "123456******3456"
Run Code Online (Sandbox Code Playgroud)

(在非块形式匹配中可用\1,\2等等.适用于简单替换,但不能调用.size它们等)

参数形式中没有Magic变量,因为调用方法之前会计算参数.因此,尚未设置变量.如果你要两次调用这样的方法,第二次你将从第一次获得匹配.

或者,你可以避免所有这个正则表达式伏都教,只是直接掩盖字符

s3 = s.dup # don't touch the original string
s3[6...-4] = '*' * (s.length - 4 - 6) # string of asterisks of variable length
s3  # => "123456******3456"
Run Code Online (Sandbox Code Playgroud)