使用Ruby扫描字符串

时间:2012-11-09 15:48:57

标签: ruby regex

我正在尝试创建一个正则表达式来从字符串中收集信息,如下所示:

A22xB67-E34...

任何数字。

我有正则表达式:

@spaceCode = "[A-Z]([A-Z0-9][0-9]|[0-9])"
@moveCode=/^(?<one>#{@spaceCode})((?<mode>x|\-)(?<two>#{@spaceCode}))+$/

但是我得到了:

s="A11-A22xA33".scan(@moveCode)
=> [["A11", "11", "xA33", "x", "A33", "33"]]

这绝对不是我想要的。

字符串可以是任何长度的C22等,其中x-作为分隔符,并将其放入如下数组:

['A22','x',B22','-'.......]

示例:

"A22xB23-D23xE25" => ['A22','x','B23','=','D23','E25;]
"AA2xA9-A1" => ['AA2','x','A9','-','A1']

4 个答案:

答案 0 :(得分:2)

据推测,您希望孤立地找到这三个字母数字代码? 这个更简单的正则表达式(或其中的变体)能做你想要的吗?

def decode string
  puts "\nDecoding #{string}"
  code = "[A-Z0-9]{1,3}"
  sep = "[-x=]"
  r = /(?:(#{code})#{sep}?)?/
  string.scan(r)
end

puts decode("A22xA33")
puts decode("A11-A22xA33")
puts decode("A22xB67-E34")
puts decode("A22xC33xD44-E55")
puts decode("A22xB23-D23=E25")

或者如果你想捕捉动作/分隔符,例如:

r = /(?:#{code}#{sep}?)?/

或将数组中的动作/分隔符捕获为代码之间的单独项:

r = /(#{code})?(#{sep})?/

所以我认为你想要的是:

def decode string
  puts "\nDecoding #{string}"
  code = "[A-Z0-9]{1,3}"
  sep = "[-x=]"
  r = /(#{code})?(#{sep})?/
  string.scan(r)
end

或以其最简单的形式:

string.scan(/([A-Z0-9]{1,3})?([-x=])?/)

答案 1 :(得分:1)

我这样做:

MOVE_REGEX = /[a-z]+\d+/i
REGEX = /(#{ MOVE_REGEX })([x-]?)/i

class String
  def parse_move
    self.scan(REGEX).flatten.reject(&:empty?)
  end
end

"A22xB23-D23xE25".parse_move
# => ["A22", "x", "B23", "-", "D23", "x", "E25"]

"AA2xA9-A1".parse_move
# => ["AA2", "x", "A9", "-", "A1"]

答案 2 :(得分:0)

使用split之类的方法,正则表达式为([x-])


您的regex不适用于您的输入,因为这会始终覆盖群组spaceCodemode,即spaceCodemode仅包含最后一个匹配的spaceCodemode

例如,输入^(\d)+$的正则表达式3664仅捕获4而非366,{{1在小组中。

答案 3 :(得分:0)

似乎这应该有效,因为字段名称可以是可变长度:

def parse_moves(s)    
  s.scan(/([A-Z0-9]+)?([-x])?/).flatten.compact
end

您的示例的结果:

1.9.3-p125 :027 > moves = ["A11-A22xA33", "A22xB23-D23xE25", "AA2xA9-A1"]
 => ["A11-A22xA33", "A22xB23-D23xE25", "AA2xA9-A1"] 
1.9.3-p125 :028 > moves.each { |s| puts parse_moves(s).to_s }
["A11", "-", "A22", "x", "A33"]
["A22", "x", "B23", "-", "D23", "x", "E25"]
["AA2", "x", "A9", "-", "A1"]