我想在字符串中匹配数字(int和real),但如果它们是标识符的一部分则不匹配;例如,我想匹配5.5或42,但不匹配x5。字符串大致为“x5 * 1.1 + 42 * y = 40”。 到目前为止,我想出了
([0-9]*[.])?[0-9]+[^.*+=<>]
这正确地忽略了x0,但也忽略了0或0.5(但是,12.45可以工作)。将+
更改为*
会导致错误的匹配。
如果有人可以指出我的错误,那将是非常好的。
谢谢!
答案 0 :(得分:1)
这实际上并不简单。 Float文字比您假设的更复杂,能够包含指数格式的Channel
或e
。此外,您可以为数字和/或指数添加带前缀的符号(E
或+
)。总而言之,它可以这样做:
-
返回:
re.findall(r'(?:(?<![a-zA-Z_0-9])|[+-]\s*)[\d.]+(?:[eE][+-]?\d+)?',
'x5*1.1+42*y=40+a123-3.14e-2')
您应该考虑['1.1', '+42', '40', '-3.14e-2']
之类的内容是否应该导致4+3
或['4', '3']
。如果输入为['4', '-3']
,则4+-3
显然更为可取。但要区分这些并不容易,你应该考虑使用适当的公式解析器。
也许标准模块'-3'
可以帮助您。在这种情况下,表达式必须是有效的Python表达式,因此不允许使用ast
之类的东西,因为等号左边没有正确的 lvalue 。但对于有效的Python对象,您可以使用a+b=40
,如下所示:
ast
返回:
import ast
def find_all_numbers(e):
if isinstance(e, ast.BinOp):
for r in find_all_numbers(e.left):
yield r
for r in find_all_numbers(e.right):
yield r
elif isinstance(e, ast.Num):
yield e.n
list(find_all_numbers(ast.parse('x5*1.1+42*y-40').body[0].value))
答案 1 :(得分:0)
你可以用
之类的东西来做\b\d*(\.\d+)?\b
它匹配任意数量的数字(\d*
),后跟可选的小数部分((\.\d+)?
)。 \b
匹配字边界,即字词和非字符之间的位置。由于数字和(英文)字母都是字符,因此它与5
之类的序列中的x5
不匹配。
尝试失败的主要原因是它以[^.*+=<>]
结尾,要求数字(或者更确切地说匹配)以{以外的字符结尾}结束{1}},.
,*
,=
,+
或<
。当以>
和0
之类的单个数字结尾时,数字会被0.5
吃掉,而且与{{1}无关离开了,因此失败了。在[0-9]+
的情况下,它首先与[^.*+=<>]
匹配,然后12.45
与12.4
匹配。
答案 2 :(得分:-1)
执行((?<![a-zA-Z_])\d+(\.\d+)?)
它使用负面的lookbehind,以便在它之前不选择任何有[a-zA-Z_]
的东西。
请在Regex101中查看。
关于正则表达式([0-9]*[.])?[0-9]+[^.*+=<>]
使用[0-9]+
代替[0-9]*
因为它不会允许.05被捕获,只有0.5。另一件事是[^.*+=<>]
这部分,您可以添加吗?到它的最后,以便它也不允许有字符。示例1.1
不会被捕获,因为([0-9]*[.])?[0-9]+
已满足,但[^.*+=<>]
也不会被捕获。