Как избежать повторного удаления в python регулярном выражении - PullRequest
1 голос
/ 29 мая 2020

Я удаляю строки из кучи файлов txt, используя регулярное выражение, используя Python; однако я столкнулся со случаем, когда иногда происходит повторное удаление, если строка содержит строку, довольно похожую на первую

s = 'market.fruit.apple'

Файл txt может содержать следующие строки

market.fruit.apple
market.fruit.apple.all

Но если я запустил

open_file = open('test.txt', 'r')
read_file = open_file.read()
r = re.compile(r"(?<!\S){0}.*(?:[\r\n]\s*)?".format(s))
read_file = r.sub('',read_file)
write_file = open('test.txt', 'w')
write_file.write(read_file)

, он удалит как market.fruit.apple, так и market.fruit.apple.all, когда нужно удалить только первый. Как мне этого избежать? Я попытался установить для параметра count значение 1, но это ничего не дало. Я думал сделать строковое сходство между строками и использовать другое регулярное выражение, если оно соответствует правильному условию, но я подумал, что это могут быть ненужные накладные расходы, если я увеличу это.

Изменить: исправлены некоторые опечатки в приведенном выше примере, можно воспроизвести в regex101.com/r/q7qWVh/1

Ответы [ 2 ]

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

Вы можете использовать

r"(?<!\S){0}[\s=].*(?:[\r\n]\s*)?".format(re.escape(s))

Обратите внимание на использование re.escape, это необходимо, поскольку вы используете переменную, представляющую буквальный текст в шаблоне регулярного выражения.

Если ваша переменная market.fruit.apple, ваше регулярное выражение будет выглядеть как

(?<!\S)market\.fruit\.apple[\s=].*(?:[\r\n]\s*)?

См. Демонстрацию регулярного выражения

Подробности

  • (?<!\S) - левая граница пробела
  • market\.fruit\.apple - ключевое слово
  • [\s=] - пробел или = символ
  • .* - любые 0 или более символов, кроме символов разрыва строки, как можно больше
  • (?:[\r\n]\s*)? - необязательная последовательность символа разрыва строки CR или LF, а затем любых 0 или более пробелов.
0 голосов
/ 29 мая 2020

Есть пара проблем с этим RegEx. Во-первых, точка в строке интерпретируется как токен «любого отдельного символа», а не буквальная точка. Его нужно экранировать с помощью backsla sh: \.. Далее, группа без захвата в конце для сопоставления пробелов является необязательной, а .* перед ней просто продолжит сопоставление символов, пока не найдет новую строку. Я также не понимаю цель первого отрицательного просмотра назад.

Что касается того, как это исправить, вот мое предложение:

1- Если вам нужно сравнить строку со строкой literal, и вы не используете какие-либо функции RegEx, вы можете просто прочитать строки и отфильтровать их как таковые:

lines = open_file.readlines()
lines = [line for line in lines if line != s]

2- Если вам это нужно в Regex, вы можете просто заменить не захватывающие группы с ^ и $, обозначающие начало и конец строки соответственно. Новое RegEx будет ^market\.fruit\.apple$, и вы можете увидеть его в действии здесь: https://regex101.com/r/pi7Wjw/1/

Не забудьте также проверить документацию библиотеки re , чтобы узнать больше. информация об использовании различных специальных символов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...