Регулярное выражение: как сопоставить последовательность пар ключ-значение в конце строки - PullRequest
6 голосов
/ 16 марта 2011

Я пытаюсь сопоставить пары ключ-значение, которые появляются в конце (длинных) строк.Строки выглядят так (я заменил «\ n»)

my_str = "lots of blah
          key1: val1-words
          key2: val2-words
          key3: val3-words"

, поэтому я ожидаю совпадения «key1: val1-words», «key2: val2-words» и «key3: val3-words».

  • Набор возможных имен ключей известен.
  • Не все возможные ключи появляются в каждой строке.
  • По крайней мере два ключа появляются в каждой строке (если этоупрощает сопоставление).
  • val-words может состоять из нескольких слов.
  • пары ключ-значение должны совпадать только в конце строки.
  • Я используюМодуль Python re.

Я думал, что

<code>re.compile('(?:tag1|tag2|tag3):')

плюс некоторые предварительные утверждения будут решением.Я не могу понять это правильно, хотяКак мне это сделать?

Спасибо.

/ David

Реальный пример строки:

my_str = u'ucourt métrage pour kino session volume 18\nThème: O sombres héros\nContraintes: sous titrés\nAuthor: nicoalabdou\nTags: wakatanka productions court métrage kino session humour cantat bertrand noir désir sombres héros mer medine marie trintignant femme droit des femmes nicoalabdou pute soumise\nPosted: 06 June 2009\nRating: 1.3\nVotes: 3'

РЕДАКТИРОВАТЬ:

На основепо решению Микеля я сейчас использую следующее:

<code>
my_tags = ['\S+'] # gets all tags
my_tags = ['Tags','Author','Posted'] # selected tags
regex = re.compile(r'''
    \n                     # all key-value pairs are on separate lines
    (                      # start group to return
       (?:{0}):            # placeholder for tags to detect '\S+' == all
        \s                 # the space between ':' and value
       .*                  # the value
    )                      # end group to return
    '''.format('|'.join(my_tags)), re.VERBOSE)</p>

<p>regex.sub('',my_str) # return my_str without matching key-vaue lines
regex.findall(my_str) # return matched key-value lines

1 Ответ

8 голосов
/ 16 марта 2011

Отрицательное предположение нулевой ширины: (?!pattern).

Это упомянуто на полпути вниз по странице документации re модуля .

(?!...)

Соответствует, если ... не соответствует следующему.Это негативное предположение.Например, Исаак (?! Азимов) будет соответствовать «Исааку», только если за ним не следует «Азимов».

Таким образом, вы можете использовать его для сопоставления любого количества слов после клавиши, но неключ, использующий что-то вроде (?!\S+:)\S+.

И полный код будет выглядеть так:

regex = re.compile(r'''
    [\S]+:                # a key (any word followed by a colon)
    (?:
    \s                    # then a space in between
        (?!\S+:)\S+       # then a value (any word not followed by a colon)
    )+                    # match multiple values if present
    ''', re.VERBOSE)

matches = regex.findall(my_str)

Что дает

['key1: val1-words ', 'key2: val2-words ', 'key3: val3-words']

Если вы напечатаете ключ /значения, используя:

for match in matches:
    print match

Будет напечатано:

key1: val1-words
key2: val2-words
key3: val3-words

Или, используя ваш обновленный пример, будет напечатано:

Thème: O sombres héros 
Contraintes: sous titrés 
Author: nicoalabdou 
Tags: wakatanka productions court métrage kino session humour cantat bertrand noir désir sombres héros mer medine marie trintignant femme droit des femmes nicoalabdou pute soumise 
Posted: 06 June 2009 
Rating: 1.3 
Votes: 3

Вы можете повернуть каждую клавишу /пара значений в словарь, используя что-то вроде этого:

pairs = dict([match.split(':', 1) for match in matches])

, что облегчит поиск только тех ключей (и значений), которые вы хотите.

Дополнительная информация:


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