Получение некоторых элементов в строке с помощью регулярного выражения - PullRequest
3 голосов
/ 09 февраля 2010

Контекст


Используя Ruby, я анализирую строки, выглядящие так:

Тип с идентификатором ...

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

... с дополнительными параметрами от 0 до n, разделенными @ ...

[Image=4b5da003ee133e8368000002@size:small]
[Image=4b5da003ee133e8368000002@size:small@media:true]

В этом примере:

[Image=4b5da003ee133e8368000002@size:small@media:true]

Я хочу получить:

  1. [Изображение = 4b5da003ee133e8368000002 @ размера: маленькие @ СМИ: истинный]
  2. Изображение
  3. 4b5da003ee133e8368000002
  4. размер: маленький
  5. СМИ: правда

Проблема


Прямо сейчас, используя это регулярное выражение:

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

Я получаю ...

  1. [Изображение = 4b5da003ee133e8368000002 @ размера: маленькие @ СМИ: истинный]
  2. Изображение
  3. 4b5da003ee133e8368000002
  4. @ СМИ: правда

Что я делаю не так? Как я могу получить то, что я хочу?

PS: Все результаты скопированы с http://rubular.com/, что хорошо для отладки регулярных выражений. Пожалуйста, используйте это, если это может помочь вам помочь мне:)


Редактировать: если невозможно разделить все параметры, как я могу получить это:

  1. [Изображение = 4b5da003ee133e8368000002 @ размера: маленькие @ СМИ: истинный]
  2. Изображение
  3. 4b5da003ee133e8368000002
  4. @ размер: маленькие @ СМИ: правда

Ответы [ 5 ]

3 голосов
/ 09 февраля 2010

Изменить:

Реализация Ruby в Regex, похоже, не поддерживает множественные захваты в одной группе , как это делают большинство других движков regex. Поэтому вам придется сделать два шага; сначала получить все @*:* в одну строку, а затем разделить их.

Чтобы получить их все, это должно сработать:

(\[([a-zA-Z]+)=([a-zA-Z0-9]+)((?:@[a-zA-Z]+:[a-zA-Z]+)*)\])
2 голосов
/ 09 февраля 2010

Чтобы получить «хвост» опций, вы можете получить его из $4 с помощью

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

и затем split на знаках.

Например:

#! /usr/bin/ruby

str = "[Image=4b5da003ee133e8368000002@size:small@media: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

Выход:

[Image=4b5da003ee133e8368000002@size:small@media:true]
Image
4b5da003ee133e8368000002
@size:small@media:true
size:small
media:true
1 голос
/ 09 февраля 2010

Хотя это может быть сложно сделать просто в регулярном выражении, его не так сложно разделить на две операции:

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]
[Image=4b5da003ee133e8368000002@size:small]
[Image=4b5da003ee133e8368000002@size:small@media:true]
[Image=4b5da003ee133e8368000002@size:small@media:true@foo:bar]

Это производит вывод:

Image / 4b5da003ee133e8368000002 / 
Video / 679hfpam9v56dh800khfdd32 / 
Image / 4b5da003ee133e8368000002 / size:small
Image / 4b5da003ee133e8368000002 / size:small,media:true
Image / 4b5da003ee133e8368000002 / size:small,media:true,foo:bar
1 голос
/ 09 февраля 2010

Похоже, что регулярное выражение сохраняет только последний матч. Я думаю, что для получения списка матчей потребуется другой подход.

"a=b@c:d@e:f".split(/=|@/)

, который создает список:

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

что близко к тому, что вы хотите ...

1 голос
/ 09 февраля 2010
(\[([a-zA-Z]+)=([a-zA-Z0-9]+)(?:@([a-zA-Z]+:[a-zA-Z]+))*\])

даст вам медиа: правда. Обратите внимание, что media: true перезаписывает предыдущий размер: маленькое совпадение. Я не думаю, что есть способ получить именно то, что вы хотите за один матч матча.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...