Как удалить слово, если оно имеет более 2 вхождений данного символа в Python?

#python #regex #parsing

#python #регулярное выражение #синтаксический анализ

Вопрос:

Я анализирую файл журнала, в котором есть строки типа:

 Pushing the logs into /var/log/my_log.txt
Pushing the logs into /opt/test/log_file.txt
  

Существует несколько вхождений этих строк с автоматически сгенерированными путями (/…/…/…)

Я хочу изменить это в общую форму, например:

  Pushing the logs into PATH
  

Я попытался использовать регулярное выражение для выбора слова с несколькими косыми чертами, а затем заменить его словом «ПУТЬ» следующим образом:

 line = re.sub(r'b([/A-Z]*/[A-Z]*){1,}b',' PATH ',line)
  

Заменяются только косые черты, но не все слово.

Очень ново для этой концепции. Я делаю что-то не так? Любая помощь приветствуется. Спасибо.

Комментарии:

1. попробуйте, re.sub("/.*", 'PATH', line)

Ответ №1:

Вы могли бы использовать:

 import re

line = 'Pushing the logs into /var/log/my_log.txt'

pat = r'(?<!S)(/S ){2,}'

line = re.sub(pat, 'PATH', line)

print(line)
  

Это не отвечает точно так, как указано, потому что оно ищет «слова», которые должны начинаться с / , а также содержать два или более / (с другими символами, не содержащими пробелов после каждого / ) — так что это будет охватывать, например, /tmp/my_log.txt . Я думаю, что это лучше охватывает вид строк, которые вы найдете — если они являются абсолютными путями, то / всегда будет первым символом, и аналогично, если это файлы, а не каталоги, то последний / не будет в конце ( хотя я не потрудился исключить a / в конце при условии, что перед ним также есть по крайней мере два). Если вы хотите искать только, например, 3 или более / (не в конце), то измените 2 на 3, но вы пропустите /tmp/my_log.txt , если сделаете это.

Первый бит регулярного выражения (?<!S) является отрицательным утверждением lookbehind, означающим «не предшествует символ без пробелов», то есть он будет соответствовать началу «слова» или началу строки. Следующий бит (/S ) означает / , за которым следует один или несколько символов, не содержащих пробелов (которые могут включать / — это не имеет значения, поэтому я не потрудился исключить их). И {2,} означает, что их должно быть два или более.

(Я использую «word» здесь, как и в вопросе, для обозначения последовательности символов, не содержащих пробелов, не обязательно букв.)

Ответ №2:

Сопоставляются только прямые косые черты, потому что строка написана в нижнем регистре, а шаблон соответствует нулю или более раз либо косой черте, либо символу верхнего регистра от АдоЯ, используя [/A-Z]*

Вы могли бы сделать шаблон нечувствительным к регистру, используя re.IGNORECASE но он не будет соответствовать подчеркиванию и точке в данных примера.

Первая косая черта не сопоставляется при запуске шаблона с границей слова b , но между пробелом и первой косой чертой нет границы слова.

Немного более конкретное соответствие может быть использовано w для сопоставления символа слова и указания точки для расширения:

 (?<!S)(?:/w ) /w .w (?!S)
  
  • (?<!S) Установите границу пробела слева
  • (?:/w ) Сопоставьте 1 или более раз / , за которыми следует 1 слово символов
  • /w .w Сопоставьте последнее / , за которым следует формат имени файла, используя символы точки и слова
  • (?!S) Установите границу пробела справа

Смотрите демонстрация регулярных выражений | Демонстрация Python

 import re

line = 'Pushing the logs into /var/log/my_log.txt'
line = re.sub(r'(?<!S)(?:/w ) /w .w (?!S)', 'PATH', line)
print(line)
  

Вывод

 Pushing the logs into PATH
  

Более широкий шаблон может соответствовать 2-кратной косой черте и использовать класс отрицаемых символов для соответствия любому символу, кроме косой черты или новой строки

 (?<!S)(?:/[^/rn] ){2,}
  

Смотрите другую демонстрацию регулярных выражений