正则表达式负先行实现

Regex negative lookahead implementations

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

我必须在数字部分后将 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 并匹配任务 3,但无法匹配任务 4。

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

为此,您可以使用

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

regex demo

详情

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

在Python中,使用

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

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

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

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

*+ 0 or more 量词是占有性的,一旦数字、逗号和点匹配,模式将永远不会重试,负先行检查将只执行一次。

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,.]*))(?!\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

鉴于您的意见:

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$

是的!另一个 RegEx 问题!

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

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