带可选范围的正则表达式匹配号

2024-10-02 10:27:23 发布

您现在位置:Python中文网/ 问答频道 /正文

使用python的re module,我试图从以下语句中获取美元值:

  • “$305000-$349950”应该给出这样的元组(305000349950)
  • “200万美元左右的买家”->;(2000000)
  • “。。。买家指南$129万+“-->;(129万)
  • “…$485000和$510000”->;(485000510000)

下面的模式适用于单个值,但如果有范围(如上面的第一个和最后一个点),它只给出最后一个数字(即349950和510000)。在

_pattern = r"""(?x)
    ^
    .*
    (?P<target1>
        [€$£]
        \d{1,3}
        [,.]?
        \d{0,3}
        (?:[,.]\d{3})*
        (?P<multiplyer1>[kKmM]?\s?[mM]?)
    )
    (?:\s(?:\-|\band\b|\bto\b)\s)?
    (?P<target2>
        [€$£]
        \d{1,3}
        [,.]?
        \d{0,3}
        (?:[,.]\d{3})*
        (?P<multiplyer2>[kKmM]?\s?[mM]?)
    )?
    .*?
    $
    """

当尝试target2 = match.group("target2").strip()时,target2总是None。在

我绝不是一个监管专家,但我不能真正看到我做错了什么。乘法器组工作正常,在我看来,target2组是相同的模式,也就是说,最后是可选匹配。在

我希望我的措辞有点可以理解。。。在


Tags: gtre指南模式数字语句pattern元组
2条回答

+1用于对regex模式使用详细模式

模式开头的.*是贪婪的,所以它试图匹配整行。然后它回溯以匹配target1。模式中的其他所有内容都是可选的,因此将target1与行中的最后一个匹配匹配是成功的匹配。您可以尝试通过添加“?”来使第一个.*不贪婪是这样的:

_pattern = r"""(?x)
    ^
    .*?                   <  add the ?
    (?P<target1>
    ... snip ...
    """

你能逐步做到吗?在

^{pr2}$

编辑 还有一个想法:试试看关于芬德尔():

_pattern = r"""(?x)
    (?P<target1>
        [€$£]
        \d{1,3}
        [,.]?
        \d{0,3}
        (?:[,.]\d{3})*
        (?P<multiplyer1>[kKmM]?\s?[mM]?)
    )
"""

targets = re.findall(_pattern, line)

你可以想出一些正则表达式逻辑和一个转换缩写数字的函数相结合。下面是一些python代码示例:

# -*- coding: utf-8> -*-
import re, locale
from locale import *
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') 

string = """"$305,000 - $349,950"
"Mid $2M's Buyers"
"... Buyers Guide $1.29M+"
"...$485,000 and $510,000"
"""

def convert_number(number, unit):
    if unit == "K":
        exp = 10**3
    elif unit == "M":
        exp = 10**6
    return (atof(number) * exp)

matches = []
rx = r"""
    \$(?P<value>\d+[\d,.]*)         # match a dollar sign 
                                    # followed by numbers, dots and commas
                                    # make the first digit necessary (+)
    (?P<unit>M|K)?                  # match M or K and save it to a group
    (                               # opening parenthesis
        \s(?:-|and)\s               # match a whitespace, dash or "and"
        \$(?P<value1>\d+[\d,.]*)    # the same pattern as above
        (?P<unit1>M|K)?
    )?                              # closing parethesis, 
                                    # make the whole subpattern optional (?)
"""
for match in re.finditer(rx, string, re.VERBOSE):
    if match.group('unit') is not None:
        value1 = convert_number(match.group('value'), match.group('unit'))
    else:
        value1 = atof(match.group('value'))
    m = (value1)
    if match.group('value1') is not None:
        if match.group('unit1') is not None:
            value2 = convert_number(match.group('value1'), match.group('unit1'))
        else:
            value2 = atof(match.group('value1'))
        m = (value1, value2)
    matches.append(m)

print matches
# [(305000.0, 349950.0), 2000000.0, 1290000.0, (485000.0, 510000.0)]

代码使用了相当多的逻辑,它首先为atof()函数导入locale模块,定义一个函数convert_number(),并使用代码中解释的正则表达式搜索范围。显然,您可以添加其他货币符号,如€$£,但它们不在您最初的示例中。在

相关问题 更多 >

    热门问题