将 SVG 'd'属性正确拆分为令牌的正则表达式是什么?



我正在尝试将 svg 文件中路径标签上的d属性拆分为标记。

这个相对容易:

d = "M 2 -12 C 5 15 21 19 27 -2 C 17 12 -3 40 5 7"
tokens = d.split(/[s,]/)

但这也是一个有效的d属性:

d = "M2-12C5,15,21,19,27-2C17,12-3,40,5,7"

棘手的部分是字母和数字不再分开,负数仅使用负号作为分隔符。如何创建处理此问题的正则表达式?

规则似乎是:

  • 在有空格或逗号的地方拆分
  • 将数字与字母分开(并将"-"与数字保持在一起)

我知道我可以使用环顾四周,例如:

tokens = pathdef.split(/(?<=d)(?=D)|(?<=D)(?=d)/)

我在形成一个正则表达式时遇到问题,该正则表达式也会在减号上拆分,并将减号与数字一起保留

上面的代码应按如下方式标记:

[ 'M', '2', '-12', 'C', '5', '15', '21', '19', '27', '-2', 'C', '17', '12', '-3', '40', '5', '7' ]

简介

不幸的是,JavaScript 不允许回溯,所以你的选择相当有限,下面其他正则表达式引擎部分中的正则表达式对你不起作用(尽管它会与其他一些正则表达式引擎一起使用)。

其他正则表达式引擎

注意:本节中的正则表达式(其他正则表达式引擎)在 Javascript 中不起作用。请改为查看代码部分中的 JavaScript 解决方案。

我认为使用您的原始正则表达式,您正在尝试:

[, ]|(?<![, ])(?=-|(?<=[a-z])d|(?<=d)[a-z])

此正则表达式允许您拆分这些匹配项(,,或后跟-?d+(?:.d+)?|[a-z]的位置,或字母在数字之前的位置或数字在字母之前的位置)。


法典

var a = [
"M 2 -12 C 5 15 21 19 27 -2 C 17 12 -3 40 5 7",
"M2-12C5,15,21,19,27-2C17,12-3,40,5,7"
]
var r = /-?(?:d*.)?d+|[a-z]/gi
a.forEach(function(s){
console.log(s.match(r));
});


解释

  • -?d+(?:.d+)?匹配以下任一条件
    • -?
      • -匹配(?:d*.)?字面意思是零次或一次
        • d*匹配以下零次或一次
          • .匹配任意位数
          • d+匹配文字点
      • [a-z]匹配一个或多个数字
    • a-z匹配i范围内的任何字符(任何小写字母字符 - 由于使用了修饰符(?:d*.)?这也匹配这些字母的大写变体)

我添加了d是因为(据我所知)您可以在 SVGd+(?:.d+)?属性中使用十进制数字值。

注意:将(?:d*.)?d+的原始正则表达式部分更改为.5,以便根据@Thomas捕获没有整数部分的数字,例如CC_21(请参阅下面的评论问题)。

你可以去

-?d+|[A-Z]

regex101.com 上观看演示。在这里,与其拆分,不如完全匹配它们


matches = "M 2 -12 C 5 15 21 19 27 -2 C 17 12 -3 40 5 7".match(/-?d+|[A-Z]/g)
# matches holds the different tokens

最新更新