Когда вы имеете дело с исключениями, самый простой и безопасный способ - использовать подход " лучший трюк за все время ". При замене этот трюк означает: сохранить то, что захвачено, удалить то, что соответствует или наоборот. В терминах регулярных выражений вы должны использовать чередование и группу захвата вокруг одного (или некоторых в сложном сценарии ios) из них, чтобы иметь возможность анализировать структуру совпадений после совпадение найдено.
Итак, сначала , используйте список исключений для построения первой части чередования:
exception_rx = "|".join(map(re.escape, exceptions))
Примечание re.escape
добавляет обратные слеши, где необходимо поддерживать любые специальные символы в исключениях. Если ваши исключения все alphanumeri c, вам это не нужно, и вы можете просто использовать exception_rx = "|".join(exceptions)
. Или даже exception_rx = rf'\b(?:{"|".join(exceptions)})\b'
, чтобы сопоставлять их только как целые слова.
Далее , вам нужен шаблон, который найдет все совпадения независимо от контекста, тот, который я уже опубликовал :
generic_rx = r'(?<=\d)(?=[^\d\s])|(?<=[^\d\s])(?=\d)'
Наконец , соедините их по схеме (exceptions_rx)|generic_rx
:
rx = re.compile(rf'({exception_rx})|{generic_rx}', re.I)
и замените с помощью .sub()
:
s = rx.sub(lambda x: x.group(1) or " ", s)
Здесь lambda x: x.group(1) or " "
означает возвращать значение группы 1, если группа 1 соответствует, в противном случае заменить пробелом .
См. Демонстрационную версию Python :
import re
exceptions = ['1st','2nd','10th','100th','1st nation','xlr8','5pin','h20', '12th'] # '12th' added
exception_rx = '|'.join(map(re.escape, exceptions))
generic_rx = r'(?<=\d)(?=[^\d\s])|(?<=[^\d\s])(?=\d)'
rx = re.compile(rf'({exception_rx})|{generic_rx}', re.I)
string_lst = ['1ST DEF 100CD','ABC 1ST 100CD','WEST 12TH APARTMENT']
for s in string_lst:
print(rx.sub(lambda x: x.group(1) or " ", s))
Выход:
1ST DEF 100 CD
ABC 1ST 100 CD
WEST 12TH APARTMENT