2011-01-09 3 views
3

私はRuby 1.9を使用していますが、これを行うための単純な正規表現があるのだろうかと思います。数のペアが可変である場合、文字列を "キー"/"値"のペアに分割する正規表現ですか?

str = "Allocation: Random, Control: Active Control, Endpoint Classification: Safety Study, Intervention Model: Parallel Assignment, Masking: Double Blind (Subject, Caregiver, Investigator, Outcomes Assessor), Primary Purpose: Treatment" 

アイデアは、私はその機能コンポーネントに

  • 配分をこの文字列を破るしたいということです::
  • ランダム

    私はこのいくつかのバリエーションのように見える多くの文字列を持っています

  • コントロール:アクティブコントロール
  • エンドポイント分類:安全性試験
  • Interventイオンモデル:パラレル割り当て
  • マスキング:二重盲検(件名、介護者、研究者、アウトカム、評価機関)
  • 主な目的:治療

は、文字列の「構文は」」があるということですキー "は、1つまたは複数の"単語または他の文字 "(例えば、 Intervention Model)に続いてコロン(:)が続きます。各キーには対応する「値」(コロン(:))の直後に並んでいるパラメタがあります。「値」は単語、コンマ(何でも)で構成されますが、「値」の終わりはコンマ。

キー/値のペアの数は可変です。私はまた、コロン(:)が "値"の一部であることが許されておらず、コンマ(、)が "キー"の一部であることは許されないと仮定しています。

これをコンポーネントの部分に分解する「regexy」方法があるとは思うかもしれませんが、適切な一致正規表現を作成しようとすると、最初のキーと値のペアのみが取り出され、キャプチャ方法はわかりません他人。他のマッチをキャプチャする方法についての任意の考えですか?

regex = /(([^,]+?): ([^:]+?,))+?/ 
=> /(([^,]+?): ([^:]+?,))+?/ 
irb(main):139:0> str = "Allocation: Random, Control: Active Control, Endpoint Classification: Safety Study, Intervention Model: Parallel Assignment, Masking: Double Blind (Subject, Caregiver, Investigator, Outcomes Assessor), Primary Purpose: Treatment" 
=> "Allocation: Random, Control: Active Control, Endpoint Classification: Safety Study, Intervention Model: Parallel Assignment, Masking: Double Blind (Subject, Caregiver, Investigator, Outcomes Assessor), Primary Purpose: Treatment" 
irb(main):140:0> str.match regex 
=> #<MatchData "Allocation: Random," 1:"Allocation: Random," 2:"Allocation" 3:" Random,"> 
irb(main):141:0> $1 
=> "Allocation: Random," 
irb(main):142:0> $2 
=> "Allocation" 
irb(main):143:0> $3 
=> " Random," 
irb(main):144:0> $4 
=> nil 

答えて

6
irb(main):003:0> pp Hash[ *str.split(/\s*([^,]+:)\s+/)[1..-1] ] 
{"Allocation:"=>"Random,", 
"Control:"=>"Active Control,", 
"Endpoint Classification:"=>"Safety Study,", 
"Intervention Model:"=>"Parallel Assignment,", 
"Masking:"=> 
    "Double Blind (Subject, Caregiver, Investigator, Outcomes Assessor),", 
"Primary Purpose:"=>"Treatment"} 

正規表現の空白部分が必要ですが、少し出力をクリーンアップするのに役立つされていません。キーの末尾からコロンを削除するか、値からカンマを後で削除するなど、フォローアップマイナークリーンアップを実行するようにしておきます。

+1

ニース、エレガントな答え。 – vonconrad

+0

ありがとう。それはうまくいくようですが、私はそれを完全に理解していません。 split(/ \ s *([^、] +:)\ s + /)を呼び出す方法は、基本的に「キーを見つけて分割する」と言っています。もしそうなら、どのように/なぜ "分割"して、キーを配列に転送しますか?さて、私は分割方法について新しいことを学んだと思う。 str.split(/:/)を実行すると、配列内のコロンが得られません。 str.split(/(:)/)を実行すると、配列のコロンが得られます**これは明らかだったのでしょうか?私はb/cにはrdocからは明らかではないように思っています。 – user141146

+0

はい、キャプチャグループが結果に含まれています。'\ s *'と '\ s +'をグループ外に置くことで、それらは含まれません。 'string#split'から抜粋:_ patternがRegexpの場合、strはパターンが一致するところで分割されます。パターンが長さゼロの文字列に一致すると、strは個々の文字に分割されます。それぞれの一致が同様に配列に返されます** " – Phrogz

2

は、いくつかの試行錯誤の後、私は次はあなたの例の文字列と正規表現で動作するように得ることができた:

str.split(/((?:[^,]+?): (?:[^:]+?,(?![^\(]+?\))))+?/).delete_if(&:empty?).map{|s| s.strip.chomp(',')} 

私はどんなカッコ内のカンマは無視されることを保証するために、先読みを追加する必要がありました、グループの一部をミュートすることができます。最後のdelete_ifmapは純粋に化粧品です。

関連する問題