Reg Ex 表示字符串中的特定数字



>我想匹配字符串中的数字(int和real),但如果它们是标识符的一部分,则不匹配;例如,我想匹配5.5或42,但不是x5。字符串大致采用"x5*1.1+42*y=40"的形式。 到目前为止,我想出了

([0-9]*[.])?[0-9]+[^.*+=<>]

这正确地忽略了 x0,但也忽略了 0 或 0.5(但是 12.45 有效)。将+更改为*会导致错误的匹配。

如果有人能指出我的错误,那就太好了。

谢谢!

这其实并不简单。 浮点文字比您想象的要复杂,能够包含指数格式的eE。 此外,您可以为数字和/或指数添加前缀符号(+-)。 总而言之,它可以像这样完成:

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'更可取。 但是要区分这些并不容易,您应该考虑为这些使用适当的公式解析器。

也许标准模块ast可以帮助您。 在这种情况下,表达式必须是有效的 Python 表达式,因此不允许使用a+b=40之类的东西,因为等号的左侧不是正确的左值。 但是对于有效的 Python 对象,您可以使用这样的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.1, 42, 40]

你可以用类似的东西来做到这一点

bd*(.d+)?b

它匹配任意数量的数字(d*),后跟可选的小数部分((.d+)?)。b匹配单词边界,即单词字符和非单词字符之间的位置。而且由于数字和(英文)字母都是单词字符,因此它不会像x5这样的序列中的5匹配。

请参阅此正则表达式 101 示例。

您的尝试失败的主要原因是它以[^.*+=<>]结尾,这要求数字(或更确切地说是匹配)以.*=+<>以外的字符结尾。当以单个数字结尾时,如00.5,该数字被[0-9]+吃掉,并且没有与剩下的[^.*+=<>]相匹配,因此它失败了。在12.45的情况下,它首先匹配12.4然后[^.*+=<>]匹配5

执行类似((?<![a-zA-Z_])d+(.d+)?)

的操作它使用负回溯,以便不选择任何在其之前具有[a-zA-Z_]的内容。 在正则表达式 101 中查看它。

关于您的正则表达式([0-9]*[.])?[0-9]+[^.*+=<>]使用[0-9]+而不是[0-9]*,因为它不允许捕获 .05,只有 0.5。另一件事是[^.*+=<>]这部分,您可以添加 ?到最后,以便允许它也没有字符。示例1.1不会被捕获,因为([0-9]*[.])?[0-9]+满意,但也不会[^.*+=<>]它之后

相关内容

  • 没有找到相关文章

最新更新