Как исправить мой шаблон Regex, чтобы получить 3 блока значений - PullRequest
1 голос
/ 04 марта 2020

У меня есть 2 вида строк, которые нужно разбить на 3 группы с одним регулярным выражением

line1 = """NAME1;address;10461;427144.70;012020;244312:countername1::244312:countername2::244312:countername3::[!]:1:service1:410630.15:62:penny:16514.55:;1;"""

line2 = """NAME2;ADDRESS2;10458;1853.12;012020;[!]:1:service1:1853.12:62:penny:0.00:;1;"""

my_regex1 = r'^(?P<acc>.+;.+;.+;.+;.+);(?P<counters>.*:?.*):\[\!\]:(?P<services>.*):;1;$'

my_regex2 = r'^(?P<acc>.+;.+;.+;.+;.+);(?P<counters>.*:){0,}:?\[\!\]:(?P<services>.*):;1;$'

Результат первого регулярного выражения в строке1, как строки, в порядке, но в строке 2 он не работает как строки

    re.findall(my_regex1, line1) >>> 
[('NAME1;address;10461;427144.70;012020',     '244312:countername1::244312:countername2::244312:countername3:', '1:service1:410630.15:62:penny:16514.55')]

но он вообще не перехватывает строку 2

2-е регулярное выражение разрывает строку 2, но завершается неудачно с блоком счетчиков в строке 1

    re.findall(my_regex2, line2) >>> [('NAME2;ADDRESS2;10458;1853.12;012020', '', '1:service1:1853.12:62:penny:0.00')] #which s ok, but it fails with line2

re.findall(my_regex2, line1)

 >>>
    [('NAME1;address;10461;427144.70;012020','244312:countername1::244312:countername2::244312:countername3::','1:service1:410630.15:62:penny:16514.55')]     

Мне нужно исправить регулярное выражение 2, чтобы он мог разбить все строки правильно, теперь происходит сбой с добавлением нежелательного символа «:» в конец блока. Блок счетчиков может вообще не существовать или иметь более 9 полей, но блок служб всегда будет существовать, но может быть любым длиной

Ответы [ 2 ]

1 голос
/ 05 марта 2020

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

Обратите внимание, что .+; сначала будет соответствовать до конца строки и может быть написано с использованием отрицательного символьного класса [^\r\n;]+;, соответствующего любому символу, кроме ; или новой строки, чтобы предотвратить пересечение разрывов строк.

^(?P<acc>[^\r\n;]+(?:;[^\r\n;]+){4});(?:(?P<counters>.+?:):)?\[\!]:(?P<services>.*):;1;$

По частям

  • ^ Начало строки
  • (?P<acc> Именованная группа acc
    • [^\r\n;]+ Совпадение 1+ раз с любым символом, кроме символ новой строки или ;
    • (?:;[^\r\n;]+){4} Повторите 4 раза для сопоставления ; и 1+ раз для любого символа, кроме ; или символа новой строки
  • ); Закрыть группа и совпадение ;
  • (?: группа без захвата
    • (?P<counters>.+?:): именованная группа counters (соответствует второму :) после группы
  • )? Закрыть группу и сделать ее необязательной
  • \[\!]: Соответствовать [!]:
  • (?P<services>.*) Named gr oup services, соответствует 0+ раз любому символу, кроме новой строки
  • :;1; Соответствует буквально
  • $ Конец строки

Regex демо

0 голосов
/ 05 марта 2020
answer1 = "^(?P<acc>[^\r\n;]+(?:;[^\r\n;]+){4});(?:(?P<counters>.+?:):)?\[\!\]:(?P<services>.*):;1;$"
answer2 = "^(?P<acc>(?:[^;]+;){4}[^;]+);(?:(?P<counters>.*?):)?\[!]:(?P<services>.*):;1;$"
...