Разобрать строку, связанную с svg, с помощью регулярных выражений в python - PullRequest
1 голос
/ 09 мая 2020

Я хотел бы разобрать команды атрибута d в элементе пути svg . И хотелось бы, чтобы это было эффективно. Поэтому я решил использовать go с функцией регулярного выражения, чтобы избежать использования нескольких циклов.

Чего я хочу добиться, так это поместить букву команды вместе с ее значениями numeri c в кортеж и сохранить все эти кортежи в списке, например [('M', '3', '18'), ('h', '10'), ...]

В зависимости от буквы команды может быть от одного до шести числовых c значений. Эти числовые c значения могут содержать точку ('.45'), минус ('-3') или оба ('-.55'). И не всегда их разделяют пробелы. например, 'c -.55.45 0 1 '.

Мой подход:

Вот то, что я пробовал до сих пор. Я пробовал разделить их методом re.findall. Но после этого мне пришлось сгруппировать их с дополнительным l oop, и эти связанные числовые c значения с точками все еще связаны. Кроме того, я хотел бы интегрировать метод 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')]

Эти соединенные точками числа c значения кажутся простыми. Я просто разделяю их по точкам. Но это невозможно, потому что у меня могло быть значение вроде «1,55». Но тогда это значение отделяется пробелом от другого значения ('.55 1.45'). Поскольку у меня были проблемы с этими шаблонами регулярных выражений, было бы здорово, если бы у кого-то было решение или, по крайней мере, мог бы направить меня в правильном направлении.

Если я что-то пропустил или вам нужна дополнительная информация, просто скажите мне и я их предоставлю. Заранее спасибо!

1 Ответ

1 голос
/ 09 мая 2020

Если может быть только от нуля до шести аргументов, лучшее, что вы можете сделать с подходом с одним регулярным выражением, - это использовать

re.findall("([mMzZlLhHvVcCsSqGtTaA])(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?", d)

См. демонстрацию регулярных выражений . Шаблон (?:\s*(-?\d*\.?\d+))? повторяется 6 раз, чтобы сопоставить от 1 до 6 аргументов и захватить каждый из них в свою группу. (?:...)? - необязательная группа без захвата, \s*(-?\d*\.?\d+) соответствует 0+ пробелов (\s*), (-?\d*\.?\d+) захватывает в группу необязательный - (-?), 0+ цифр (\d*) , необязательная точка (\.?) и 1+ цифр (\d+).

См. Python демо :

import re
d = 'M0 0h24v24H0z'   
commands = re.findall(r"([mMzZlLhHvVcCsSqGtTaA])(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?(?:\s*(-?\d*\.?\d+))?", d)
print([tuple(list(filter(None, x))) for x in commands])
# => [('M', '0', '0'), ('h', '24'), ('v', '24'), ('H', '0'), ('z',)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...