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)

正規表現だけでやりたいことはできますか?

4

2 に答える 2

0

このような階層データを保存する場合は、正規表現を使用して文字列を解析するのではなく、YAMLを使用する方がよい場合があります。

groups.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/] }'Members'を別の単語として含む行を拒否します。
  • slice_before(/^group/)文字列の先頭にある「group」で始まるチャンクに配列を分割します。
  • to_aすべてを再び配列に変換します。
于 2012-09-27T20:08:17.263 に答える