Ruby:将嵌套数组的字符串表示解析为Array?

假设我有字符串

"[1,2,[3,4,[5,6]],7]" 

我如何将其解析为数组

 [1,2,[3,4,[5,6]],7] 

在我的使用案例中,嵌套结构和模式完全是任意的。

我目前的临时解决方案是在每个时段之后添加一个空格并使用YAML.load ,但是如果可能的话我想要一个更干净的空间。

(如果可能的话,不需要外部库)

正在使用JSON正确解析该特定示例:

 s = "[1,2,[3,4,[5,6]],7]" #=> "[1,2,[3,4,[5,6]],7]" require 'json' #=> true JSON.parse s #=> [1, 2, [3, 4, [5, 6]], 7] 

如果这不起作用,您可以尝试通过eval运行字符串,但您必须确保没有传递实际的ruby代码,因为eval可以用作注入漏洞。

编辑:这是一个简单的递归,基于正则表达式的解析器,没有validation,没有经过测试,没有用于生产用途等:

 def my_scan s res = [] s.scan(/((\d+)|(\[(.+)\]))/) do |match| if match[1] res << match[1].to_i elsif match[3] res << my_scan(match[3]) end end res end s = "[1,2,[3,4,[5,6]],7]" p my_scan(s).first #=> [1, 2, [3, 4, [5, 6]], 7] 

使用Ruby标准的libaray YAML可以完成同样的操作,如下所示:

 require 'yaml' s = "[1,2,[3,4,[5,6]],7]" YAML.load(s) # => [1, 2, [3, 4, [5, 6]], 7] 

“显然”最好的解决方案是编写自己的解析器。 [如果你喜欢编写解析器,以前从未这样做过,想要学习新的东西,或者想要控制精确的语法]

 require 'parslet' class Parser < Parslet::Parser rule(:space) { str(' ') } rule(:space?) { space.repeat(0) } rule(:openbrace_) { str('[').as(:op) >> space? } rule(:closebrace_) { str(']').as(:cl) >> space? } rule(:comma_) { str(',') >> space? } rule(:integer) { match['0-9'].repeat(1).as(:int) } rule(:value) { (array | integer) >> space? } rule(:list) { value >> ( comma_ >> value ).repeat(0) } rule(:array) { (openbrace_ >> list.maybe.as(:list) >> closebrace_ ).as(:arr)} rule(:nest) { space? >> array.maybe } root(:nest) end class MyTransform < Parslet::Transform rule(:int => simple(:x)) { Integer(x) } rule(:op => '[', :cl => ']') { [] } rule(:op => '[', :list => subtree(:x), :cl => ']') { Array(x) } rule(:arr => subtree(:x)) { x } end def parse(s) MyTransform.new.apply(Parser.new.parse(s)) end parse " [ 1 , 2 , [ 3 , 4 , [ 5 , 6 , [ ]] ] , 7 ] " 

使用eval

 array = eval("[1,2,[3,4,[5,6]],7]")