Python:捕获并返回量词中的每个元素
给定这样一组字符串:Python:捕获并返回量词中的每个元素,python,regex,Python,Regex,给定这样一组字符串:60=60,100=60+30+10,200=120+50+30,300=200+100,180=60+50+40+20+10我需要一个正则表达式来解析(并验证)这些字符串。匹配应严格(例如,数字和运算符之间不允许有空格) 我最终得到了一个类似于(\d+)=(\d+(:\+(\d+)))* 它完美地匹配了它们,但使用re.match(regex,string).groups()提取匹配项时返回('100','60','10'),('200','120','30') 请参阅,*
60=60
,100=60+30+10
,200=120+50+30
,300=200+100
,180=60+50+40+20+10
我需要一个正则表达式来解析(并验证)这些字符串。匹配应严格(例如,数字和运算符之间不允许有空格)
我最终得到了一个类似于(\d+)=(\d+(:\+(\d+)))*
它完美地匹配了它们,但使用re.match(regex,string).groups()提取匹配项时返回('100','60','10')
,('200','120','30')
请参阅,*
量词仅匹配最后一个数字!这是意料之中的,但不能解决我的问题
在*
量词下分别返回所有匹配项的最适合的方法是什么?因此我可以轻松地断言res[0]==sum(res[1:])
目前,我独立地匹配每个位,存储最后一个匹配位置并从该位置继续解析,但它看起来有点难看。如果+
是您可以得到的唯一运算符,(正如我从您提到的sum()
的事实中所假设的那样),您不需要正则表达式。只需使用常规的.split()
:
如果+
是您可以获得的唯一运算符(根据您提到的sum()
),那么您不需要正则表达式。只需使用常规的.split()
:
不使用正则表达式,而是使用解析器怎么样
from pyparsing import *
integer = Word(nums).setParseAction(lambda t:int(t[0]))
variable = Word(alphas,exact=1)
operand = integer | variable
expop = Literal('^')
signop = oneOf('+ -')
multop = oneOf('* /')
plusop = oneOf('+ -')
factop = Literal('!')
equalop = Literal('=')
expr = operatorPrecedence( operand,
[("=", 2, opAssoc.LEFT),
("+", 2, opAssoc.RIGHT),]
)
test=['60=60', '70=10+20', '100=1+2+42+67']
for t in test:
print t, u'→', expr.parseString(t)
print
然后输出:
60=60 → [[60, '=', 60]]
70=10+20 → [[[70, '=', 10], '+', 20]]
100=1+2+42+67 → [[[100, '=', 1], '+', [2, '+', [42, '+', 67]]]]
然后要得到整数,只需展平树并查找所有整数
另一种方法是在+
和=
上拆分字符串,我发现这种方法稍微不那么优雅,并且不会对字符串进行语法检查:
for t in test:
head, tail = t.split('=')
values = [head] + tail.split('+')
print t, u'→', values
其中:
60=60 → ['60', '60']
70=10+20 → ['70', '10', '20']
100=1+2+42+67 → ['100', '1', '2', '42', '67']
最后,我们可以试着找到一个regex魔弹来回答你的问题,但老实说,这不是我解决这个问题的方法
注意:要将列表展平,有一种方法:
def flatten(seq):
res = []
for item in seq:
if (isinstance(item, (tuple, list))):
res.extend(flatten(item))
else:
res.append(item)
return res
不使用正则表达式,而是使用解析器怎么样
from pyparsing import *
integer = Word(nums).setParseAction(lambda t:int(t[0]))
variable = Word(alphas,exact=1)
operand = integer | variable
expop = Literal('^')
signop = oneOf('+ -')
multop = oneOf('* /')
plusop = oneOf('+ -')
factop = Literal('!')
equalop = Literal('=')
expr = operatorPrecedence( operand,
[("=", 2, opAssoc.LEFT),
("+", 2, opAssoc.RIGHT),]
)
test=['60=60', '70=10+20', '100=1+2+42+67']
for t in test:
print t, u'→', expr.parseString(t)
print
然后输出:
60=60 → [[60, '=', 60]]
70=10+20 → [[[70, '=', 10], '+', 20]]
100=1+2+42+67 → [[[100, '=', 1], '+', [2, '+', [42, '+', 67]]]]
然后要得到整数,只需展平树并查找所有整数
另一种方法是在+
和=
上拆分字符串,我发现这种方法稍微不那么优雅,并且不会对字符串进行语法检查:
for t in test:
head, tail = t.split('=')
values = [head] + tail.split('+')
print t, u'→', values
其中:
60=60 → ['60', '60']
70=10+20 → ['70', '10', '20']
100=1+2+42+67 → ['100', '1', '2', '42', '67']
最后,我们可以试着找到一个regex魔弹来回答你的问题,但老实说,这不是我解决这个问题的方法
注意:要将列表展平,有一种方法:
def flatten(seq):
res = []
for item in seq:
if (isinstance(item, (tuple, list))):
res.extend(flatten(item))
else:
res.append(item)
return res
尝试python内置函数eval
在运行时计算表达式。我把正则表达式改成了一点点。它是通用的,可以很容易地用于任何数学运算
import re
data = "100=60+30+10, 200=120+50+30, 300=200+100, 180=60+50+40+20+10"
rx = r"(\d+)=([^, ]+)"
for res in re.finditer(rx, data, re.IGNORECASE | re.MULTILINE):
lhs = eval(res.group(1))
rhs = eval(res.group(2))
assert lhs == rhs
如果您想从代码片段中获得一些乐趣,请将regex替换为:
rx = r"([+-]?\d+(?:\.\d+))=([^, ]+)"
现在您也可以计算正数、负数、整数和十进制数。尝试python内置函数eval
在运行时计算表达式。我把正则表达式改成了一点点。它是通用的,可以很容易地用于任何数学运算
import re
data = "100=60+30+10, 200=120+50+30, 300=200+100, 180=60+50+40+20+10"
rx = r"(\d+)=([^, ]+)"
for res in re.finditer(rx, data, re.IGNORECASE | re.MULTILINE):
lhs = eval(res.group(1))
rhs = eval(res.group(2))
assert lhs == rhs
如果您想从代码片段中获得一些乐趣,请将regex替换为:
rx = r"([+-]?\d+(?:\.\d+))=([^, ]+)"
现在您也可以计算正数、负数、整数和十进制数。使用正则表达式(Python 2.7)似乎很容易解决:
使用正则表达式(Python 2.7)似乎很容易解决:
总是有两个+
操作符吗?不,我会添加更多的例子。请参阅下面我的帖子。您也可以轻松地计算+-和十进制数,不会有太多困难。为什么数字和运算符之间不允许有空格。那样太复杂了吗?您是在验证还是在解析??您不会使用Pythons regex引擎单独获取所有RHS值。只要像这样匹配它,(\d+)=(\d+(?:\+\d+*)
,组1是LHS,组2必须在+
上拆分以形成一个数组。总结数组,将其与LHS值进行比较。是否总是有两个+
运算符?不,我将添加更多示例请参阅下面的帖子。您也可以轻松地计算+-和十进制数,不会有太多困难。为什么数字和运算符之间不允许有空格。那样太复杂了吗?您是在验证还是在解析??您不会使用Pythons regex引擎单独获取所有RHS值。只要像这样匹配它,(\d+)=(\d+(?:\+\d+*)
,组1是LHS,组2必须在+
上拆分以形成一个数组。对数组求和,并将其与LHS值进行比较。它将用空格100=50+30+20
匹配字符串,但它们应该匹配fail@dmzkrsk:好的。我添加了.strip()
等一下。你想让它失败吗?它本来是我的风格,但现在我更改了它,我不确定这是否是您想要的。它将匹配带空格的字符串100=50+30+20
,但它们应该匹配fail@dmzkrsk:好的。我添加了.strip()
等一下。你想让它失败吗?它本来是我的风格,但现在我改变了它,我不确定这是否是你想要的。