【问题标题】:Python Regex to match a string as a pattern and return numberPython Regex 将字符串匹配为模式并返回数字
【发布时间】:2011-09-16 16:31:54
【问题描述】:

我有一些行代表文本文件中的一些数据。它们都是以下格式:

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 作为数字返回,但我忽略了它,因为它现在无法正确找到该数字,只会返回错误。

【问题讨论】:

  • 您的问题是在正则表达式末尾使用.*?? 使它变得懒惰,这意味着它将匹配尽可能少的字符,因此如果您以 .*? 结束正则表达式,它将不会匹配任何字符。要么为您的 n1 组删除 ?,要么在正则表达式的末尾添加 $,以便强制匹配到行尾。
  • 删除 ?在 n1 组结束时成功了!非常感谢。我必须牢记这一点,从现在开始要更加小心。

标签: python regex substring match


【解决方案1】:

试试这个:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-05-07
        • 2021-03-07
        • 1970-01-01
        • 2019-03-14
        • 2014-08-05
        • 2016-09-22
        • 2023-03-31
        相关资源
        最近更新 更多