Замена текста с помощью RE - разрешить первое возникновение, заменить оставшееся - PullRequest
2 голосов
/ 16 апреля 2020

Я ищу несколько мыслей о том, как я смог бы выполнить sh эти задачи:

  • Разрешить первое вхождение проблемы_ слова, но запретить любое его последующее использование и остальные проблемных слов.
  • Нет изменений в исходном документе (файл .txt). Изменить только для печати ().
  • Сохраняйте ту же структуру электронной почты. Если есть разрывы строк, табуляции или странные пробелы, дайте им сохранить их целостность.

Вот пример кода:

import re

# Sample email is "Hello, banned1. This is banned2. What is going on with
# banned 3? Hopefully banned1 is alright."
sample_email = open('email.txt', 'r').read()


# First use of any of these words is allowed; those following are banned
problem_words = ['banned1', 'banned2', 'banned3']


# TODO: Filter negative_words into overused_negative_words
banned_problem_words = []
for w in problem_words:
    if sample_email.count(f'\\b{w}s?\\b') > 1:
        banned_problem_words.append(w)


pattern = '|'.join(f'\\b{w}s?\\b' for w in banned_problem_words)


def list_check(email, pattern):
    return re.sub(pattern, 'REDACTED', email, flags=re.IGNORECASE)


print(list_check(sample_email, pattern))
# Result should be: "Hello, banned1. This is REDACTED. What is going on with
# REDACTED? Hopefully REDACTED is alright."

1 Ответ

2 голосов
/ 16 апреля 2020

Аргумент repl для re.sub может принимать функцию, которая принимает объект соответствия и возвращает строку замены. Вот мое решение:

import re

sample_email = open('email.txt', 'r').read()

# First use of any of these words is allowed; those following are banned
problem_words = ['banned1', 'banned2', 'banned3']

pattern = '|'.join(f'\\b{w}\\b' for w in problem_words)

occurrences = 0

def redact(match):
    global occurrences
    occurrences += 1
    if occurrences > 1:
        return "REDACTED"
    return match.group(0)

replaced = re.sub(pattern, redact, sample_email, flags=re.IGNORECASE)
print(replaced)

(Как еще примечание, string.count не поддерживает регулярное выражение, но нет необходимости считать)

...