【发布时间】:2020-05-09 10:22:57
【问题描述】:
我想解析 svg 的路径元素中的 d 属性命令。我想以一种有效的方式做到这一点。因此,我决定使用正则表达式函数来避免使用多个循环。
我想要实现的是将命令字母及其数值放在一个元组中,并将所有这些元组存储在一个列表中,例如[('M', '3', '18'), ('h', '10'), ...]
根据命令字母的不同,后面可以有 1 到 6 个数值。这些数值可以有一个点('.45')或一个减号('-3')或两者都有('-.55')。并且并不总是有空格分隔它们。例如'c -.55.45 0 1 '.
我的方法:
这是我到目前为止所尝试的。我试图用 re.findall 方法将它们分开。但在那之后,我不得不用一个额外的循环对它们进行分组,并且那些带有点的连接数值仍然是连接的。此外,我想将 replace 方法集成到 findall 模式中。
# Just an extract of a d command
d = 'M20 3H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16'
commands = re.findall("[mMzZlLhHvVcCsSqGtTaA]|[0-99\-.]+", d.replace("-", " -"))
#output: ['M', '20', '3', 'H', '4', 'c', '-.55', '0', '-1', '.45', '-1', '1', 'v', '6', 'c', '0', '.55.45', '1', '1', '1', 'h', '16']
#goal: [('M', '20', '3'), ('H', '4'), ('c', '-.55', '0', '-1', '.45', '-1', '1'), ('v', '6'), ('c', '0', '.55', '.45', '1', '1', '1'), ('h', '16')]
那些虚线连接的数值似乎很简单。我只是在点上将它们分开。但这是不可能的,因为我可以有一个像“1.55”这样的值。但随后这个值用空格分隔到另一个值('.55 1.45')。由于我在使用这些正则表达式模式时遇到了困难,如果有人有解决方案或者至少可以引导我走向正确的方向,那就太棒了。
如果我遗漏了什么或者您需要更多信息,请告诉我,我会提供。提前谢谢!
【问题讨论】:
-
如果可以有 1 到 6 个参数,使用一个正则表达式方法的最佳方法是使用
re.findall("([mMzZlLhHvVcCsSqGtTaA])\s*(-?\d*\.?\d+)(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?", d)。但是你最终会因为缺少参数而得到空项目。见ideone.com/MrA8UQ。而且您将无法使用单个正则表达式摆脱它们,您需要使用另一个列表理解进行后处理。 -
@Wiktor Stribiżew 谢谢!这对我有很大帮助。我使用过滤器对列表进行后期处理,以消除那些空字符串。但是,如果我解析
M0 0h24v24H0z这个例子,z 就会丢失。如何修改模式? -
那是因为你所有的论点似乎都是可选的,我以为至少有1个,你说可以有1到6个。所以,使用ideone.com/lWDjW4
-
z 和 Z 没有参数。带参数的命令通常可以重复参数,因此 M 后面可以有无数对参数。
-
您似乎没有考虑过路径有多复杂,例如a9.62 9.62 0 110-.05 是具有 6 值的弧。 110-.05 实际上有 1 1 0 -0.05
标签: python python-3.x regex svg python-re