改变我的正则表达式不再有循环

时间:2014-05-07 19:31:19

标签: ruby regex

我有一个符合我想要的正则表达式,它可以获得所有31或更低的数字并将它们放在自己的行上。现在我想要做的就是不再有循环,但我不知道该怎么做并需要一些帮助。

x = IO.read(path)
x.split(/\D+/).select {|n| n.to_i >= 0 && n.to_i < 32 && n.length < 3}.join("\n")

输入

1
10
12
18 19 20
21 22 ----asdfadsf 23t24####25,26,27,
28!
29.
30
31
32
33
01 02 03x04x05x06x07x08x09
001
002
1x1a
    35


-87 76 101 10057

-13 -1.5

输出-1 10 12 18 19 20 21 22 23 24 25 26 27 28 29 三十 31 01 02 03 04 05 06 07 08 09 1 1 13 1 五 (每个人都有自己的行,但我不想让它太长)

非常感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

您可以将scan与前瞻和后瞻一起使用:

puts x.scan(/(?<!\d)([0-2]?\d|3[0-1])(?!\d)/).join("\n")

使用正则表达式here

进行游戏

答案 1 :(得分:1)

你可以做很多事。我首先提取数字的字符串表示并将它们放在一个数组中:

str.scan(/\d+/).select { |n| n.to_i < 32 }
   .map { |s| (s[0,2]=='00') ? s[1..-1] : s }
  #=> [ "1", "10", "12", "18",  "19",  "20",` "21", "22", "23", "24", "25",
  #    "26", "27", "28", "29",  "30",  "31", "01", "02", "03", "04", "05",
  #    "06", "07", "08", "09",  "01",  "02",  "1",  "1", "13",  "1",  "5"]

现在您可以以任何您想要的格式打印出结果。你说你不想要这些线太长。然后你可能会这样做:

def print_it(str, max_line_len, nbr_spacers)
  arr = str.scan(/\d+/).select { |n| n.to_i < 32 }
           .map { |s| (s[0,2]=='00') ? s[1..-1] : s }
  fld_width = arr.max_by(&:size).size + nbr_spacers
  arr.each_slice(max_line_len/fld_width)
     .each { |slice| puts slice.map { |s| s.rjust(fld_width) }.join }
end

print_it(str, 60, 3)
    1   10   12   18   19   20   21   22   23   24   25   26
   27   28   29   30   31   01   02   03   04   05   06   07
   08   09   01   02    1    1   13    1    5

.map { |s| (s[0,2]=='00') ? s[1..-1] : s }

是将两个前导零减少到只有一个,这会影响两个条目('001''002')。如果您不关心这一点,只需消除表达式的那一部分。

答案 2 :(得分:0)

以下是匹配数字1到31的简单单正则表达式

^(?:3[01]|[12]?[0-9])$

它有效,但如果你不确定你可以通过投掷数字来测试它:)