0

我需要一行 gsub 来替换字符串中的所有非数字,但前提是非数字不超过三个并且数字的总长度为 10

我有这个符合第一个条件

p "0177/385490".gsub(/((\d+)\D?(\d+)\D?(\d+)\D?+(\d+))/,'\2\3\4\5') 
#=>"0177385490"

但是当我尝试这个时,{10} 检查不起作用

p "0177/385490".gsub(/((\d+)\D?(\d+)\D?(\d+)\D?+(\d+)){10}/,'\2\3\4\5') 
#=>"0177/385490"

请问该怎么做?

编辑

我设法做到了这样,但是如何在单行 gsub 中做到这一点?

strings = [
   "0473/385 490",
   "0473/385490",
   "0473 38 54 90",
   "0473/385 4901"    #this one is't captured
 ]

 strings.each do |s|
   if /((\d+)\D?(\d+)\D?(\d+)\D?+(\d+))/ =~ s
     if "#{$2}#{$3}#{$4}#{$5}".length == 10
       puts "#{$2}#{$3}#{$4}#{$5}"
     end
   end
 end

编辑:为了说明为什么它真的需要在我的例程中成为在线 gsub,将会添加更多替换

def cleanup text
  replacements = [
     {:pattern => /(04\d{2}) (\d{2}) (\d{2}) (\d{2})/, :replace_with => '\1\2\3\4'},
     {:pattern => /(0\d)(\/| |-)(\d{3}) (\d{2}) (\d{2})/, :replace_with => '\1\3\4\5'},
     {:pattern => /(\d{6} )(\d{3})-(\d{2})/, :replace_with => '\1\2 \3'},
     {:pattern => /(\d{2,4})\D?(\d{2,3})\D?(\d{2,3})/, :replace_with => '\1\2\3'}
  ].each{|replacement|text.gsub!(replacement[:pattern], replacement[:replace_with])}
  text
end
4

5 回答 5

3

我认为单行gsub不会过于可读。这是我的方法:

chars, non_chars = s.each_char.partition { |c| c =~ /\d/ }
puts chars.join if chars.size == 10 && non_chars.size <= 3

干净易读,没有任何神奇的变量。另外,它清楚地显示了您对字符串施加的规则。

于 2012-06-21T12:08:15.353 回答
3

这是一个带有 gsub 的单行代码,主要是为了说明为什么 Michael Kohl 的方法更好:

(digits = s.gsub(/\D/, '')).length == 10 && s.length < 14 ? digits : s
于 2012-06-21T12:20:13.320 回答
1

你可以使用这样的东西:

puts s.gsub(/\D/, '') if (/\A(\d\D?){10}\z/ =~ s) && (/\A(\d+\D){0,3}\d*\z/ =~ s)
于 2012-06-21T12:24:44.987 回答
1

您可能还想了解该scan方法。

strings.each do |s|
  numbers = s.scan(/\d/).join
  non_numbers = s.scan(/\D/)
  puts numbers if numbers.length == 10 && non_numbers.length < 4
end

但我更喜欢@MichaelKohl 的解决方案。

然后是一个愚蠢的例子:

strings.select{|s| s.scan(/\D/).length < 4}.map{|s| s.scan(/\d/).join}.select{|s| s.length==10}
于 2012-06-21T12:32:49.023 回答
0

谢谢大家,但我无法使用答案,因为我无法将它们插入我的日常工作(编辑我的答案以使其更清楚)。自己找到了解决方案。我按要求给每个有单行解决方案的人投票,现在我仍然需要找到一种方法将我的块作为替换模式插入到清理例程中

p "0177/3854901".gsub(/(\d+)\D?(\d+)\D?(\d+)\D?+(\d+)/){ |m| "#{$1}#{$2}#{$3}#{$4}".length==10 ? "#{$1}#{$2}#{$3}#{$4}":m} 
#=> "0177/3854901" isn't replaced because it has 11 digits
p "0177/385490".gsub(/(\d+)\D?(\d+)\D?(\d+)\D?+(\d+)/){ |m| "#{$1}#{$2}#{$3}#{$4}".length==10 ? "#{$1}#{$2}#{$3}#{$4}":m} 
#=> "0177385490"
于 2012-06-21T12:42:08.700 回答