Python正则表达式匹配字符串作为模式并返回数字

5

我可以翻译,以下是需要翻译的内容:

我有一些用文本文件表示数据的行。它们都遵循以下格式:

s = 'TheBears      SUCCESS Number of wins : 14'

它们都以名称开头,然后是空格和文本 'SUCCESS Number of wins : ',最后是获胜次数 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)

到目前为止,我的程序可以返回名称,但麻烦在此之后出现了。它们都有文本“SUCCESS Number of wins:”,所以我的想法是找到一种匹配这个文本的方法。但我意识到,我目前匹配精确子字符串的方法不正确。是否有一种方法可以将整个子字符串作为模式的一部分进行匹配?最近我一直在阅读正则表达式的相关内容,但没有找到类似的东西。我还是编程方面的新手,感谢任何帮助。
最终,我会使用float()将n1作为数字返回,但我省略了这一步,因为它现在无法正确找到数字,并且只会返回错误。

2
你的问题在于正则表达式末尾使用了 .*?? 使其成为惰性匹配,意味着它将尽可能少地匹配字符,因此如果以 .*? 结尾,则不会匹配任何字符。要么在你的 n1 组中去掉 ? ,要么在正则表达式末尾添加 $ ,这样它就会被强制匹配到行尾。 - Andrew Clark
删除 n1 组末尾的问号就解决了问题!非常感谢。我以后会记住这一点,并更加小心的。 - Simos Anderson
3个回答

3

试着用这个:

((\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()

如果您不需要完整的字符串,只需删除括号即可。

2

我认为在这里实际上没有必要使用正则表达式。因此,如果您认可以下代码,请使用它(请注意,我已经发布了它,以便您可以获得另一个选项):

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]

1
如果中间的文本始终不变,则无需使用正则表达式。内置的字符串处理函数将更高效、更易于开发、调试和维护。在这种情况下,您可以使用内置的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}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接