Регулярное выражение для обнаружения и замены строк дублированными группами захвата для удаления дубликатов пакетов в файле требований pip.txt

Файл Python requirements.txt недействителен, если он имеет разные версии. для того же пакета, представленного в виде строк ниже (предполагается, что файл отсортирован):

agate==1.6.0
agate==1.7.0

Я пытаюсь написать регулярное выражение для обнаружения дубликатов пакетов (а не строк, поскольку версии могут отличаться). Моя группа захвата представлена ​​как ^([^=]+)==.+$. Удаление повторяющихся строк близок к решению, поскольку он использует обратную ссылку для последней строки, но моя обратная ссылка будет только для группы захвата, а не для всей строки.


person Rafael Borja    schedule 13.08.2020    source источник


Ответы (2)


Обнаружьте эти строки с помощью

(?sm)^([^=]+)==.*\n\1==

См. доказательство.

ОБЪЯСНЕНИЕ

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  ^                        the beginning of the line
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    [^=]+                    any character except: '=' (1 or more
                             times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  ==                       '=='
--------------------------------------------------------------------------------
  .*                       any character (0 or more times
                           (matching the most amount possible))
--------------------------------------------------------------------------------
  \n                       '\n' (newline)
--------------------------------------------------------------------------------
  \1                       what was matched by capture \1
--------------------------------------------------------------------------------
  ==                       '=='

Питон:

import re
regex = r"^([^=]+)==.*\n\1=="
test_str = "agate==1.6.0\nagate==1.7.0"
containsDupe = bool(re.search(regex, test_str, re.MULTILINE | re.DOTALL))
person Ryszard Czech    schedule 13.08.2020
comment
Замена \n на ^ экономит шаг, так как не нужно откатывать \n. Вы также можете сэкономить один дополнительный шаг, удалив последний =. Это технически избыточно, так как вы используете [^=]. ^([^=]+)==.*\1^= - person ctwheels; 13.08.2020
comment
Спасибо за подробное объяснение! - person Rafael Borja; 13.08.2020
comment
Опечатка в моем предыдущем комментарии (не могу редактировать последние 5 минут): ^([^=]+)==.*^\1= - person ctwheels; 13.08.2020

Следующее регулярное выражение работало в отсортированном файле с использованием функции замены Notepad++

REGEX ^(.*)(==[\d\.]+)(\r?\n\1)==[\d\.]+$ ЗАМЕНИТЬ: $1$2

Как это работает:

Первая часть регулярного выражения захватывает две группы

  1. ^(.*) : Имя пакета (звездочка строки, затем любой символ до == (во второй группе)
  2. (==[\d\.]+): знаки равенства и версия пакета (любая комбинация цифр и точек после знаков равенства)

Вторая часть регулярного выражения соответствует следующему имени пакета в следующей строке с захваченной 1-й группой, где

  • (\r?\n\1) : Соответствует первой группе захвата
  • ==[\d\.]+$: соответствует имени пакета во второй строке.

Замена использует $1$2, где

  • $1: первая группа захвата с именем пакета
  • $2: Вторая группа захвата с версией пакета со знаками равенства
person Rafael Borja    schedule 13.08.2020