Регулярное выражение: удаление многострочных комментариев, но сохранение разрыва строки и однострочных комментариев в начале новой строки

#python #regex

Вопрос:

Следующий ввод выглядит следующим образом

 int 1; //integer
//float 1; //floating point number
int m; //integer
/*if a==b
begin*/
print 23 /* 1, 2, 3*/
end
float/* ty;
int yu;*/
 

Ожидаемый результат выглядит следующим образом

 int 1; //integer
int m; //integer
print 23 
end
float
 

Ответ №1:

Вот двухэтапная замена, которая, похоже, работает:

 inp = """int 1; //integer
//float 1; //floating point number
int m; //integer
/*if a==b
begin*/
print 23 /* 1, 2, 3*/
end
float/* ty;
int yu;*/"""

output = re.sub(r'^s*//.*?n', '', inp, flags=re.M)
output = re.sub(r'n?/*.*?*/(n?)', r'1', output, flags=re.M|re.S)
print(output)
 

Это печатает:

 int 1; //integer
int m; //integer
print 23 
end
float
 

Первый вызов re.sub удаляет все строки, начинающиеся с // комментария. Второй вызов re.sub удаляет /* */ комментарии в стиле C. Он работает, пытаясь сопоставить новую строку как до, так и после самого комментария. Затем он заменяет столько, сколько только на одну новую строку, предполагая, что она следует за комментарием.

Ответ №2:

Вы можете преобразовать следующие совпадения в пустые строки.

 //.*r?n|//.*|^/*[sS]*?*/r?n|/*[sS]*?*/
 

ДЕМОНСТРАЦИЯ

Обратите внимание, что второй элемент чередования должен следовать за первым, а четвертый элемент чередования должен следовать за третьим.

Регулярное выражение можно разбить следующим образом.

 (?m)       # set multiline flag 
  ^//    # match '//' at beginning of line
  .*r?n  # match 0  chars other than line
           # terminators then match line terminator
|          # or
  //.*   # match '//'
  .*       # match the remainder of the line
|          # or
  ^/*    # match '/*' at the beginning of a line
  [sS]*? # match 0  characters including line
           # terminators, lazily
  */     # match '*/'
  r?n    # match line terminators
|          # or
  */     # match '*/'
  [sS]*? # match 0  characters including line
           # terminators, lazily
  */     # match '*/'