Удалить многострочный шаблон со специальными символами из файла

#python #regex #python-3.x

#python #регулярное выражение #python-3.x

Вопрос:

Мне нужно удалить многострочный шаблон из файла. Например:

   <Command name="somecom" type="type" >
     <input name="some input" />
     <output name="some output" />
  </Command>
  <?ignore <Command name="somecom" type="type" >
     <input name="some input" />
     <output name="some output" />
  </Command> ?> 
  

Раздел для удаления начинается с:

  <?ignore
  

Заканчивается:

  ?>
  

Для этого я хочу использовать регулярное выражение. python3.6.3

 with open('graph.xml', 'r') as readXML:
    tempFile = readXML.read()
    patr = re.compile("<?ignore.*?>", re.MULTILINE)
    tempFile = re.sub(patr,"",tempFile)
    print(tempFile)
  

Результат:

   <Command name="somecom" type="type" >
     <input name="some input" />
     <output name="some output" />
  </Command>
  <?
     <input name="some input" />
     <output name="some output" />
  </Command> ?> 
  

Я бы хотел, чтобы был удален весь раздел, а не только частичная первая строка.

Ответ №1:

Вы можете удалить многострочные шаблоны, используя этот шаблон <?ignore. ??> :

Пример:

 import re

str = """
  <Command name="somecom" type="type" >
     <input name="some input" />
     <output name="some output" />
  </Command>
  <?ignore <Command name="somecom" type="type" >
     <input name="some input" />
     <output name="some output" />
  </Command> ?> 
  """

print(re.sub(r'<?ignore. ??>', '', str, flags=re.MULTILINE|re.DOTALL))
  

Это выводит:

   <Command name="somecom" type="type" >
     <input name="some input" />
     <output name="some output" />
  </Command>
  

Не забудьте использовать флаги, иначе замена не будет работать:

 flags=re.MULTILINE|re.DOTALL
  

Ответ №2:

Вы можете либо сделать так, чтобы точка соответствовала новой строке, используя, например, модификатор (?s) , и избежать вопросительного знака ? , чтобы соответствовать ему буквально. Вы также можете сделать подход к началу точки не жадным .*?

 (?s)<?ignore.*??>
  

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

Или вы можете использовать повторяющийся шаблон для сопоставления строки, которая не содержит ?> , используя отрицательный прогноз:

 <?ignoreb.*n(?!.*?>)(?:.*n)*.*?>
  
  • <?ignoreb.*n Сопоставление <?ignore , за которым следует 1 раз любой символ, за которым следует новая строка
  • (?!.*?>) Отрицательный прогноз, утверждать, что справа нет ?>
  • (?:.*n)* Повторите 0 раз, сопоставляя любой символ, кроме новой строки, за которой следует новая строка
  • .*?> Сопоставьте 0 раз любой символ и ?>

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

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

1. Большое спасибо за подробный ответ! Я использовал версию flags, поскольку она более дружелюбна, чем модификатор (?s)

Ответ №3:

? является необязательным квантификатором в регулярном выражении, так что a? это означает, что символ a является необязательным. Чтобы обнаружить этот символ, вам нужно его экранировать.

попробуйте с

 <?ignore.*?>
  

Ответ №4:

Это потому, что? влияет на «жадные» кванторы: * и таким образом, что делает их «ленивыми» — * и начинают искать первое появление символа / группы после них, а затем сопоставляют, возвращают. Итак, чтобы заставить ваше регулярное выражение работать, вам просто нужно escape? символ с

<?ignore.*?> будет работать так, как вы ожидаете.