Python Regex для сопоставления строки в качестве шаблона и номера возврата - PullRequest
5 голосов
/ 16 июня 2011

У меня есть несколько строк, которые представляют некоторые данные в текстовом файле. Все они имеют следующий формат:

s = 'TheBears      SUCCESS Number of wins : 14'

Все они начинаются с имени, затем пробела и текста «УСПЕХ Количество побед:» и, наконец, числа побед, n1. Есть несколько строк, каждая из которых имеет свое имя и значение. Я пытаюсь написать программу, которая может анализировать любую из этих строк и возвращать имя набора данных и числовое значение в конце строки. Я пытаюсь использовать регулярные выражения, чтобы сделать это, и я придумал следующее:

import re
def winnumbers(s):
    pattern = re.compile(r"""(?P<name>.*?)     #starting name
                             \s*SUCCESS        #whitespace and success
                             \s*Number\s*of\s*wins  #whitespace and strings
                             \s*\:\s*(?P<n1>.*?)""",re.VERBOSE)
    match = pattern.match(s)

    name = match.group("name")
    n1 = match.group("n1")

    return (name, n1)

Пока моя программа может вернуть имя, но проблема возникает после этого. У всех них есть текст «УСПЕХ Количество побед», поэтому я подумал, как найти способ сопоставить этот текст. Но я понимаю, что мой метод сопоставления точной подстроки сейчас не верен. Есть ли способ сопоставить целую подстроку как часть шаблона? В последнее время я много читал о регулярных выражениях, но ничего подобного не нашел. Я все еще новичок в программировании, и я ценю любую помощь.

В конце концов, я буду использовать float (), чтобы вернуть n1 как число, но я пропустил это, потому что сейчас он не может правильно найти номер на первом месте и будет только возвращать ошибку.

Ответы [ 3 ]

2 голосов
/ 17 июня 2011

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

dict((line[:line.lower().index('success')+1], line[line.lower().index('wins:') + 6:]) for line in text.split('\n') if 'success' in line.lower())

ИЛИ в случае, если вы уверены, что все словаразделены на один пробел:

output={}
for line in text:
    if 'success' in line.lower():
        words = line.strip().split(' ')
        output[words[0]] = words[-1]
2 голосов
/ 16 июня 2011

Попробуйте это:

((\S+)\s+SUCCESS Number of wins : (\d+))

Вот результаты:

>>> regex = re.compile("((\S+)\s+SUCCESS Number of wins : (\d+))")
>>> r = regex.search(string)
>>> r
<_sre.SRE_Match object at 0xc827cf478a56b350>
>>> regex.match(string)
<_sre.SRE_Match object at 0xc827cf478a56b228>

# List the groups found
>>> r.groups()
(u'TheBears SUCCESS Number of wins : 14', u'TheBears', u'14')

# List the named dictionary objects found
>>> r.groupdict()
{}

# Run findall
>>> regex.findall(string)
[(u'TheBears SUCCESS Number of wins : 14', u'TheBears', u'14')]
# So you can do this for the name and number:
>>> fullstring, name, number = r.groups()

Если вам не нужна полная строка, просто удалите круглые скобки.

1 голос
/ 17 июня 2011

Если текст посередине всегда постоянен, регулярное выражение не требуется.Встроенные функции обработки строк будут более эффективными, их будет легче разрабатывать, отлаживать и обслуживать.В этом случае вы можете просто использовать встроенную функцию split(), чтобы получить фигуры, а затем очистить две фигуры соответствующим образом:

>>> def winnumber(s):
...     parts = s.split('SUCCESS Number of wins : ')
...     return (parts[0].strip(), int(parts[1]))
... 
>>> winnumber('TheBears      SUCCESS Number of wins : 14')
('TheBears', 14)

Обратите внимание, что я вывел число побед в виде целого числа (предположительно, это всегда будет целое число), но вы можете легко заменить float() - или любую другую функцию преобразования - на int(), если хотите.

Редактировать : Очевидно, этобудет работать только для отдельных строк - если вы вызовете функцию с несколькими строками, это приведет к ошибкам.Чтобы обработать весь файл, я бы использовал map():

>>> map(winnumber, open(filename, 'r'))
[('TheBears', 14), ('OtherTeam', 6)]

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

>>> dict(map(winnumber, open(filename, 'r')))
{'OtherTeam': 6, 'TheBears': 14}
...