0

我有一个这样的字符串:

group1
  Members: 
  m/a
  m/b
group2
  Members: 
  m/c
  m/d
  m/e
group3
  No Members

我想要一个像这样的扫描结果:

[["group1","a","b"],["group2","c","d","e"],["group3"]]

但我可以拥有:

[["group1","a"],["group2","c"],["group3", nil]]

使用这个正则表达式:

text.scan(/([^\r\n]+)\r?\n[\s\t]*(?:No |)Members[\s:]*\r?\n(?:[\t\s]*m\/(\w+)+\r?\n)*/m)

我可以只用 regexp 做我想做的事吗?

4

2 回答 2

0

如果您想存储这样的分层数据,最好使用 YAML 而不是尝试使用正则表达式解析字符串。

组.yml:

group1:
  members: 
  - m/a
  - m/b
group2:
  members: 
  - m/c
  - m/d
  - m/e
group3:
  members: []

解析这些数据:

> YAML.load(File.open('./groups.yml'))
 => {"group1"=>{"members"=>["m/a", "m/b"]}, "group2"=>{"members"=>["m/c", "m/d", "m/e"]}, "group3"=>{"members"=>[]}} 
于 2012-09-27T17:32:58.920 回答
0

虽然可以在正则表达式中做到这一点,但它变得笨拙,所以我会这样做:

data = <<EOT
group1
  Members: 
  m/a
  m/b
group2
  Members: 
  m/c
  m/d
  m/e
group3
  No Members
EOT

pp data.lines.slice_before(/^group/).to_a
=> [["group1\n", "  Members: \n", "  m/a\n", "  m/b\n"],
    ["group2\n", "  Members: \n", "  m/c\n", "  m/d\n", "  m/e\n"],
    ["group3\n", "  No Members\n"]]

清理其余部分以满足问题的要求使其:

data.gsub(%r{\bm/}, '').split(/\n\s*/).reject{ |s| s[/\bMembers\b/] }.slice_before(/^group/).to_a
=> [["group1", "a", "b"], ["group2", "c", "d", "e"], ["group3"]]

解析的要点确实在slice_before. 其他一切都在创建数组和清理。

分解它:

  • gsub(%r{\bm/}, '')剥离不受欢迎的m/
  • split(/\n\s*/)将行尾的字符串拆分为一个数组,同时删除前导空格。
  • reject{ |s| s[/\bMembers\b/] }拒绝任何包含“成员”作为单独单词的行。
  • slice_before(/^group/)将数组分成以字符串开头的“组”开头的块。
  • to_a再次将其全部转换为数组。
于 2012-09-27T20:08:17.263 回答