或者当一个组前面必须有一个字符时,在组之间



我有以下数据:

$200 – $4,500
Points – $2,500

我想捕获美元的范围,或者捕获Points字符串(如果这是较低的范围(。

例如,如果我在上面的每个条目上运行regex,我会期望:

Group 1: 200
Group 2: 4,500

Group 1: Points
Group 2: 2,500

对于第一组,我不知道如何在允许捕获Points的情况下只捕获整数值(没有$符号(。

以下是我尝试过的:

(?:$([0-9,]+)|Points) – $([0-9,]+)

https://regex101.com/r/mD9JeR/1

只需在此处使用一个替换:

^(?:(Points)|$(d{1,3}(?:,d{3})*)) - $(d{1,3}(?:,d{3})*)$

演示

上述正则表达式模式的要点是,我们使用交替来匹配范围下端的Points或美元金额,并且我们使用以下正则表达式来匹配带逗号的美元金额:

$d{1,3}(?:,d{3})*

生成一个与$不匹配的正则表达式并不困难。得出一个与$不匹配的正则表达式,并一致地放置这两个值,无论它们都是数字还是其中一个是Points,因为捕获组1和2并不简单。如果使用命名的捕获组,困难就会消失。此正则表达式需要PyPi存储库中的regex模块,因为它多次使用相同的命名组。

import regex

tests = [
'$200 – $4,500',
'Points – $2,500'
]
re = r"""(?x)       # verbose mode
^                   # start of string
(
$              # first alternate choice
(?P<G1>[d,]+)  # named group G1
|                 # or
(?P<G1>Points)  # second alternate choice
)
x20–x20           # ' – '
$
(?P<G2>[d,]+)      # named group g2
$                   # end of string
"""

# or re = r'^($(?P<G1>[d,]+)|(?P<G1>Points)) – $(?P<G2>[d,]+)$'
for test in tests:
m = regex.match(re, test)
print(m.group('G1'), m.group('G2'))

打印:

200 4,500
Points 2,500

更新

@marianc的评论是正确的,但没有确保输入中没有多余的字符。因此,有了他有用的投入:

import re

tests = [
'$200 – $4,500',
'Points – $2,500',
'xPoints – $2,500',
]

rex = r'((?<=^$)d{1,3}(?:,d{3})*|(?<=^)Points) – $(d{1,3}(?:,d{3})*)$'
for test in tests:
m = re.search(rex, test)
if m:
print(test, '->', m.groups())
else:
print(test, '->', 'No match')

打印:

$200 – $4,500 -> ('200', '4,500')
Points – $2,500 -> ('Points', '2,500')
xPoints – $2,500 -> No match

请注意,由于在行的开头执行的后备断言不可能成功,因此会执行search而不是match。但是,通过在我们的后备断言中包含^锚,我们在行的开头不强制使用无关字符。

对于第一个捕获组,您可以使用与Points匹配的交替,并断言左侧是非空白字符,或者使用可选的十进制值来匹配数字,断言左侧是美元符号(如果支持的话(。

对于第二个捕获组,没有其他选择,因此您可以匹配美元符号,并在组2中捕获具有可选十进制值的数字。

((?<=$)d{1,3}(?:,d{3})*|(?<!S)Points) – $(d{1,3}(?:,d{3})*)

解释

  • (捕获组1
    • (?<=$)d{1,3}(?:,d{3})*正向查找,向左断言一个$并匹配1-3位数字,并重复0+匹配逗号和3位数字
    • |
    • (?<!S)Points正向查找,在左侧断言一个非空白字符并匹配点
  • )关闭组1
  • 按字面匹配
  • $匹配$
  • (捕获组2
    • d{1,3}(?:,d{3})*匹配1-3位数字和0+倍逗号和3位数字
  • )关闭组

Regex演示

相关内容

最新更新