Python正则匹配字符串并返回数字

5 投票
3 回答
11300 浏览
提问于 2025-04-16 19:43

我有一些行数据,它们存储在一个文本文件里,格式都是这样的:

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转换成数字,但我现在先不提这个,因为目前程序还不能正确找到这个数字,只会返回错误。

3 个回答

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)

注意,我输出的胜利次数是整数(因为这通常是一个整数),但如果你需要的话,可以很容易地把 int() 替换成 float() 或其他任何转换函数。

编辑:显然,这个方法只适用于单行文本——如果你用这个函数处理多行文本,它会报错。要处理整个文件,我建议使用 map()

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

另外,我不太确定你最终想怎么用这段代码,但你可能会发现把输出作为字典来处理会更方便:

>>> dict(map(winnumber, open(filename, 'r')))
{'OtherTeam': 6, 'TheBears': 14}
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]
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()

如果你不需要完整的字符串,只需去掉外面的括号就可以了。

撰写回答