3


0

正規表現を使用して文字列内のいくつかの要素を取得する

コンテキスト

'' '' '

Rubyを使用して、次のような文字列を解析しています。

IDを持つタイプ…​

[Image=4b5da003ee133e8368000002]
[Video=679hfpam9v56dh800khfdd32]

…​with between 0 and n additional options separated with @…​

この例では:

取得したい:

  1. [画像= 4b5da003ee133e8368000002 @ size:small @ media:true]

  2. 画像

  3. 4b5da003ee133e8368000002

  4. サイズ:小

  5. media:true

問題

'' '' '

現在、この正規表現を使用しています:

(\[([a-zA-Z]+)=([a-zA-Z0-9]+)(@[a-zA-Z]+:[a-zA-Z]+)*\])

私は…

  1. [画像= 4b5da003ee133e8368000002 @ size:small @ media:true]

  2. 画像

  3. 4b5da003ee133e8368000002

  4. @media:true

何がおかしいのですか? 欲しいものを手に入れるにはどうすればいいですか?

PS:すべての結果はhttp://rubular.com/からコピーされます。これは正規表現をデバッグするのに便利です。 あなたが私を助けるのを助けることができるならば、それを使ってください:)

'' '' '

編集:すべてのオプションを分離することが不可能な場合、どうすればこれを取得できますか?

  1. [画像= 4b5da003ee133e8368000002 @ size:small @ media:true]

  2. 画像

  3. 4b5da003ee133e8368000002

  4. @size:small @ media:true

5 Answer


3


編集:

http://ruby-doc.org/core/classes/MatchData.html[Rubyの正規表現の実装は、他のほとんどの正規表現エンジンが行うように、1つのグループでの複数のキャプチャをサポートしていないようです。 したがって、2つのステップを実行する必要があります。最初にすべての `@ `を1つの文字列で取得してから、それらを分割します。

それらをすべて取得するには、これが機能するはずです:

(\[([a-zA-Z]+)=([a-zA-Z0-9]+)((?:@[a-zA-Z]+:[a-zA-Z]+)*)\])


2


オプションの「テール」を取得するには、 `$ 4`からそれを取得できます

/(\[([a-zA-Z]+)=([a-zA-Z0-9]+)((@[a-zA-Z]+:[a-zA-Z]+)*)\])/

そして、アットマークで「分割」します。

例えば:

#! /usr/bin/ruby

str = "[[email protected]:[email protected]:true]"
if /(\[([a-zA-Z]+)=([a-zA-Z0-9]+)((@[a-zA-Z]+:[a-zA-Z]+)*)\])/.match(str)
  print $1, "\n",
        $2, "\n",
        $3, "\n",
        $4, "\n";

  $4[1..-1].split(/@/).each do |s|
    print s, "\n";
  end
end

出力:

[[email protected]:[email protected]:true]
Image
4b5da003ee133e8368000002
@size:[email protected]:true
size:small
media:true


1


(\[([a-zA-Z]+)=([a-zA-Z0-9]+)(?:@([a-zA-Z]+:[a-zA-Z]+))*\])

media:trueを提供します。 media:trueは、以前のsize:smallマッチを上書きすることに注意してください。 1回のマッチコールで必要なものを正確に取得する方法はないと思います。


1


正規表現は最後の一致のみを保持するようです。 一致のリストを取得するには、別のアプローチが必要だと思います。

リストを作成します:

["a", "b", "c:d", "e:f"]

あなたが望むものに近い…​


1


正規表現内で純粋に行うのは難しいかもしれませんが、2段階の操作として分割するのはそれほど難しくありません。

while (line = DATA.gets)
  line.chomp!

  if (m = line.match(/\[([a-zA-Z]+)=([a-zA-Z0-9]+)((?:@[a-zA-Z]+:[a-zA-Z]+)*)\]/))
    (type, hash, options) = m.to_a[1, 3]
    options = options.split(/@/).reject { |s| s.empty? }
    puts [ type, hash, options.join(',') ].join(' / ')
  end
end

__END__
[Image=4b5da003ee133e8368000002]
[Video=679hfpam9v56dh800khfdd32]
[[email protected]:small]
[[email protected]:[email protected]:true]
[[email protected]:[email protected]:[email protected]:bar]

これにより出力が生成されます。

Image / 4b5da003ee133e8368000002 /
Video / 679hfpam9v56dh800khfdd32 /
Image / 4b5da003ee133e8368000002 / size:small
Image / 4b5da003ee133e8368000002 / size:small,media:true
Image / 4b5da003ee133e8368000002 / size:small,media:true,foo:bar