【问题标题】:Regex negative lookahead implementations正则表达式负前瞻实现
【发布时间】:2020-06-30 17:44:23
【问题描述】:

我正在尝试为我的任务实现负前瞻。

我必须在数字部分之后将kgs 添加到负前瞻中。

到目前为止,我已经尝试过this regex

total\samount\s?\:?\s?[0-9\,\.]+\s(?!kgs)(?!\ kgs)

给定文字:

task1. total amount 5,887.99 kgs
task2. total amount 5,887.99kgs
task3. total amount 5,887.99 usd
task4. total amount 5,887.99usd

我想匹配 task3task4 但不是 task1 和 task2。

到目前为止,我能够拒绝 task1/task2 并匹配 task3 但未能匹配 task4。

【问题讨论】:

    标签: python regex regex-lookarounds


    【解决方案1】:

    您可以模拟 Python re 不支持的 atomic group

    为此,您可以使用

    total\s+amount\s*(?::\s*)?(?=(\d[\d,.]*))\1(?!\s*kgs)
    

    regex demo

    详情

    • total\s+amount - total,1+ 个空格,amount
    • \s* - 0+ 个空格
    • (?::\s*)? - 一个可选组,匹配 1 次或 0 次出现的 : 和 0+ 个空格
    • (?=(\d[\d,.]*)) - 一个正向前瞻,匹配并捕获到第 1 组一个数字,然后是 0 个或多个数字、点或逗号
    • \1 - 捕获组 #1 的值(不允许回溯到反向引用,因此后续的前瞻只会触发一次,如果失败,整个匹配将失败)
    • (?!\s*kgs) - 如果有 0+ 个空格,然后在当前位置右侧紧邻 kgs,则匹配失败。

    在 Python 中,使用

    pattern = r'total\s+amount\s*(?::\s*)?(?=(\d[\d,.]*))\1(?!\s*kgs)'
    

    注意PyPi regex module 支持原子组和所有格量词,您可以只使用

    total\s+amount\s*(?::\s*)?\d[\d,.]*+(?!\s*kgs)
    #                                 ^^
    

    查看regex demo(设置了 PHP 选项,因为这将在 Python 代码中具有相同的行为)。

    *+0 或更多 量词是主动的,一旦数字、逗号和点匹配,该模式将永远不会重试,并且只会执行一次否定的前瞻检查。 p>

    Python test online

    import regex, re
    
    texts = ['task1. total amount 5,887.99 kgs','task2. total amount 5,887.99kgs','task3. total amount 5,887.99 usd','task4. total amount 5,887.99usd']
    re_rx = r'total\s+amount\s*(?::\s*)?(?=(\d[\d,.]*))\1(?!\s*kgs)'
    regex_rx = r'total\s+amount\s*(?::\s*)?\d[\d,.]*+(?!\s*kgs)'
    
    for s in texts:
        m_rx = re.search(re_rx, s)
        if m_rx:
            print("'", m_rx.group(), "' matched in '", s,"' with re pattern", sep="")
        m_regex = regex.search(regex_rx, s)
        if m_regex:
            print("'", m_regex.group(), "' matched in '", s,"' with regex pattern", sep="")
    

    输出:

    'total amount 5,887.99' matched in 'task3. total amount 5,887.99 usd' with re pattern
    'total amount 5,887.99' matched in 'task3. total amount 5,887.99 usd' with regex pattern
    'total amount 5,887.99' matched in 'task4. total amount 5,887.99usd' with re pattern
    'total amount 5,887.99' matched in 'task4. total amount 5,887.99usd' with regex pattern
    

    【讨论】:

    • 感谢您清楚地解释每个细节。 @Wiktor
    【解决方案2】:

    鉴于您的意见:

    task1. total amount 5,887.99 kgs
    task2. total amount 5,887.99kgs
    task3. total amount 5,887.99 usd
    task4. total amount 5,887.99usd
    

    并且只想匹配最后两个,似乎这应该可行:

     *usd$
    

    【讨论】:

      【解决方案3】:

      是的!另一个正则表达式问题!

      虽然这次你并没有真正指定(或澄清)你想要什么。所以我猜这个 ReGeX: [,.\d]*\ *usd 应该可以解决问题。 proof

      但如果你想提取 USD,请使用:([,.\d]*)\ *usd

      【讨论】:

        猜你喜欢
        • 2021-10-11
        • 2011-10-14
        • 2010-12-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多