作为一项练习,我试图提出一个正则表达式来评估像
这样的简单代数q = '23 * 345 - 123+65'
从这里我想得到'23','*','345',' - ','123','+','65'。
现在,我搜索过类似的问题,其他人已经解决了这个问题。但我真正想知道的是为什么我的解决方案不起作用。
这是我得到的最好的:
regexparse = '(\d+\s*(\*|\/|\+|\-)\s*)+(\d+\s*)'
解释
但是,当我运行代码时
m = re.match(regexparse, q)
print m.group(0)
print m.group(1)
print m.group(2)
print m.group(3)
我得到了
23 * 345 - 123+65
123+
+
65
所以它就像第一个块匹配尽可能少的字符。为什么呢?
答案 0 :(得分:4)
这是你的正则表达式:
(\d+\s*(\*|\/|\+|\-)\s*)+(\d+\s*)
(\d+\s*(\*|\/|\+|\-)\s*)
将与您的表达式的第一部分匹配:23 *
并将*
存储在第二组中。
然后+
使其重复,但由于重复捕获组仅保留其最后一个匹配,它将丢弃23 *
和*
,而是匹配345 -
和{{ 1}}在第二组。
-
在下一次重播时再次发挥作用,放弃上次捕获,而是捕获第一组中的+
和第二组中的123+
。
接下来,+
不能重复,所以它会停止,+
开始匹配以获取(\d+\s*)
。
重复捕获组仅存储最后一次捕获的事实是正则表达式如何按设计工作,并且在所有正则表达式引擎AFAIK中都是如此。
进一步阐述:
重复匹配和重复捕获之间存在差异。在65
上尝试:(\d)+
,您会看到只会捕获12345
。这就是因为你为帕伦分配了一个特定的群体捕获。第一组被分配了第1组,如果第1组有很多捕获,则只能保留1,而最后一组。不幸的是,这就是正则表达式的工作原理as per the docs:
如果一个组匹配多次,则只能访问最后一个匹配
如果您想获得所需的输出,可以使用5
并与re.findall
匹配:
\d+|[+/*-]
答案 1 :(得分:2)
我只能说正则表达式,因为我不知道python,但你的问题是在
(\d+\s*[\*/+-]\s*)+(\d+\s*)
这部分
(\d+\s*[\*/+-]\s*)+
正在重复,当它完全完成评估时,你只能看到最后一个。
答案 2 :(得分:2)
只需尝试一下。
import re
q = '23 * 345 - 123+65'
regexparse = r'(\d+)|[-+*/]'
for i in re.finditer(regexparse, q):
print i.group(0)
输出:
23
*
345
-
123
+
65
答案 3 :(得分:2)
你的正则表达式令人困惑。最好将re.split()
用于此目的:
q = '23 * 345 - 123+65'
print re.split('\s*([-+/*])\s*', q)
输出:
['23', '*', '345', '-', '123', '+', '65']