Что нового

Данные, строки Удалить комментарии в коде С++ скриптом AutoIt

Oki

Продвинутый
Сообщения
452
Репутация
62
Для сабжа на данный момент написан такой скрипт.
Код:
$s = FileRead(@ScriptDir & "\1.txt")
$s = StringRegExpReplace($s, "/\*(?s).*?\*/", "") ; To delete comments of the type "/*[anything]*/".
$s = StringRegExpReplace($s, "(?m)^//.*?$", "") ; To delete lines of the type "//[anything]".
$s = StringRegExpReplace($s, "//.*?((?m)$)", "\0") ; To delete right parts of lines, starting from "//[anything]".
FileWrite(@ScriptDir & "\2.txt", $s)
Не имею достаточного опыта в регулярных выражениях, чтобы получить уверенность в том, когда скрипт начнёт правильно обрабатывать любые ситуации по сабжу. Даже сейчас вижу, что второй шаг применения регулярных выражений не приводит к полному удалению строки, но не удивлюсь наличию других неточностей в этом скрипте. Прошу взглянуть опытных пользователей регулярных выражений и оценить скрипт и/или предложить к нему правки.

Последовательность действий скрипта следующая:
  • сначала удаляются комментарии, начинающиеся символами "/*" и заканчивающиеся символами "*/";
  • затем полностью удаляются строки, начинающиеся символами "//" (этого, к сожалению, не удалось достигнуть полностью: пустые строки остаются на месте удаляемых);
  • и наконец, удаляются части строк, начинающиеся символами "//".
Надеюсь, что сам план (включая последовательность действий) тоже корректен. Мнения на этот счёт также приветствуются.
 

IMStrelcov

CTPEJIbLLOB
Сообщения
253
Репутация
64
А если так?
Код:
$sText = ''
$sText &= '//Line 00 Comment text'& @CRLF
$sText &= 'Line 01 useful text'& @CRLF
$sText &= '/*Line 02 Comment text*/'& @CRLF
$sText &= '//Line 03 Comment text'& @CRLF
$sText &= 'Line 04 useful text'& @CRLF
$sText &= 'Line 05 useful text //Comment text'& @CRLF
$sText &= 'Line 06 useful text'& @CRLF
$sText &= '/**/'& @CRLF
$sText &= '//'& @CRLF
$sText &= 'Line 09 useful text'& @CRLF
$sText &= 'Line 10 useful text //'& @CRLF
$sText &= '/*Comment text*/Line 11 useful text'& @CRLF
$sText &= 'Line 12 useful text/*Comment text*/'& @CRLF
$sText &= '/*Comment text*/Line 14 useful text/*Comment text*/'& @CRLF
$sText &= 'Line 15 useful text'& @CRLF

$sOld = $sText
$sOld = StringRegExpReplace($sOld, "/\*(?s).*?\*/", "") ; To delete comments of the type "/*[anything]*/".
$sOld = StringRegExpReplace($sOld, "(?m)^//.*?$", "") ; To delete lines of the type "//[anything]".
$sOld = StringRegExpReplace($sOld, "//.*?((?m)$)", "\0") ; To delete right parts of lines, starting from "//[anything]".

$sNew = $sText
$sNew = StringRegExpReplace($sNew, "(?m)^/\*.*?\*/\v*", "") ; To delete lines of the type "/*[anything]*/".
$sNew = StringRegExpReplace($sNew, "/\*.*?\*/", "") ; To delete comments of the type "/*[anything]*/".
$sNew = StringRegExpReplace($sNew, "(?m)^//.*\v*", "") ; To delete lines of the type "//[anything]".
$sNew = StringRegExpReplace($sNew, "(?m)//.*$", "") ; To delete right parts of lines, starting from "//[anything]".

ConsoleWrite('----------Old----------'& @CRLF)
ConsoleWrite($sOld& @CRLF)
ConsoleWrite('----------New----------'& @CRLF)
ConsoleWrite($sNew& @CRLF)
ConsoleWrite('-----------------------'& @CRLF)
 
Автор
Oki

Oki

Продвинутый
Сообщения
452
Репутация
62

IMStrelcov

Нет, так не работает, но есть интересные идеи, которые попробую скомпоновать.
 
Последнее редактирование:

Andrey_A

Продвинутый
Сообщения
319
Репутация
68
Мнения на этот счёт также приветствуются.
Чтобы попробовать помочь желательно видеть файл(ы) ДО и ПОСЛЕ форматирования, у меня нет файлов C++, если приложите, то можно посмотреть...
 
Автор
Oki

Oki

Продвинутый
Сообщения
452
Репутация
62
Сделать идеальный скрипт оказалось намного сложнее, чем кое-как работающий. Мне после размышлений и тщетных попыток начинает казаться, что для идеального решения проще собственный парсер без регулярных выражений написать, который не будет связан строгими правилами регулярных выражений. Тем более, что конечная цель это и есть парсинг кода, который первоначально хотелось для простоты очистить от множественных комментариев. В итоге с конечной задачей на этот раз удалось справиться и кое-как работающим скриптом, подчистив кое-какой-мусор вручную и полуавтоматическими инструментами.
Чтобы попробовать помочь желательно видеть файл(ы) ДО и ПОСЛЕ форматирования, у меня нет файлов C++, если приложите, то можно посмотреть...
Во-первых, совершенно неважно, что там внутри. Важен лишь формат комментариев (либо двойной слеш - комментарий до конца строки, аналогичный точке с запятой в AutoIt, либо от слеша и звёздочки, открывающих комментарий, до следующих звёздочки и слеша, закрывающих его, причём во втором случае игнорируются любые попытки начать новый комментарий и все разрывы строк - здесь аналогия с многострочными комментариями AutoIt неполная, так как комментарий может быть не только многострочным, но и начинаться и обрываться в любом месте, причём даже по несколько раз за строку).

В качестве запрошенных примеров вполне можно бы использовать формально некомпилируемый текст типа того, который накапливается в текстовых переменных в скрипте первого комментатора. Но этот скрипт справляется с конкретным приведённым примером, а с другими - нет. А потому, во-вторых, подобрать скрипт под конкретный файл это не то, что годится для решения поставленной задачи.

Если уж и пытаться довести до конца решение этой задачи, то ориентироваться следует не на примеры, а на интуитивно доказуемое в своей общности решение, которое подойдёт под самые различные образцы комментариев. Это могут быть комментарии в начале или в конце файла. Многострочные, в строках с которыми как либо есть что-то ещё, так и нет ничего иного, а потому в последнем случае надо убрать их вместе с ещё одним переводом строки, который поставлен лишь для цели вставки этого комментария, причём, зависимо от источника, может проставляться тремя разными способами. А ещё могут быть так называемые закомментаренные комментарии и многое другое, так что даже несколько затруднительно строго формализовать формулировку этой интуитивно понятной задачи. Правда, компиляторы с ней справляются уж точно, но не факт, что с применением регулярных выражений.
 

IMStrelcov

CTPEJIbLLOB
Сообщения
253
Репутация
64
Можно так, пишите что не так или чего не хватает.
Код:
$sText = ''
$sText &= '//01 Comment text'& @CRLF
$sText &= @CRLF
$sText &= '01 useful text'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '//02 Comment text'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '02 useful text'& @CRLF
$sText &= '/*03 Comment text*/'& @CRLF
$sText &= '//04 Comment text'& @CRLF
$sText &= '03 useful text'& @CRLF
$sText &= '04 useful text //05 Comment text'& @CRLF
$sText &= '05 useful text'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '/**/'& @CRLF
$sText &= '//'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '06 useful text'& @CRLF
$sText &= '/*06 Comment'& @CRLF
$sText &= 'text*/07 useful text'& @CRLF
$sText &= '08 useful text //'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '/*07 Comment text*/09 useful text'& @CRLF
$sText &= '10 useful text/*08 Comment text*/'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '/*09 Comment text*/11 useful text/*10 Comment text*/'& @CRLF
$sText &= '12 useful text'& @CRLF
$sText &= '/*11 Comment text*/13 useful text/*12 Comment text*/'& @CRLF
$sText &= '/*13 Comment text*/14 useful text/*14 Comment'& @CRLF
$sText &= 'text*/'& @CRLF

$sOld = $sText
$sOld = StringRegExpReplace($sOld, "/\*(?s).*?\*/", "") ; To delete comments of the type "/*[anything]*/".
$sOld = StringRegExpReplace($sOld, "(?m)^//.*?$", "") ; To delete lines of the type "//[anything]".
$sOld = StringRegExpReplace($sOld, "//.*?((?m)$)", "\0") ; To delete right parts of lines, starting from "//[anything]".

$sNew = $sText
$sNew = StringRegExpReplace($sNew, "//[^\v]*", "") ; удалить комент после //
$sNew = StringRegExpReplace($sNew, "(?s)/\*.*?\*/\v*?", "") ; удалить комент между /* и */
$sNew = StringRegExpReplace($sNew, "(\v+)", @CRLF) ; удалить пустые строки
$sNew = StringRegExpReplace($sNew, "(^\v+|\v+$)", '') ; удалить перенос строки в начале и конце текста

ConsoleWrite('----------Old----------'& @CRLF)
ConsoleWrite($sOld& @CRLF)
ConsoleWrite('----------New----------'& @CRLF)
ConsoleWrite($sNew& @CRLF)
ConsoleWrite('-----------------------'& @CRLF)
 

RaZum

Знающий
Сообщения
78
Репутация
14
(?m)^\h*//.*$\R - удаляет строки // вместе с пробелами в начале и переносом строки
 
Автор
Oki

Oki

Продвинутый
Сообщения
452
Репутация
62
Можно так, пишите что не так или чего не хватает.
Код:
$sText = ''
$sText &= '//01 Comment text'& @CRLF
$sText &= @CRLF
$sText &= '01 useful text'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '//02 Comment text'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '02 useful text'& @CRLF
$sText &= '/*03 Comment text*/'& @CRLF
$sText &= '//04 Comment text'& @CRLF
$sText &= '03 useful text'& @CRLF
$sText &= '04 useful text //05 Comment text'& @CRLF
$sText &= '05 useful text'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '/**/'& @CRLF
$sText &= '//'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '06 useful text'& @CRLF
$sText &= '/*06 Comment'& @CRLF
$sText &= 'text*/07 useful text'& @CRLF
$sText &= '08 useful text //'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '/*07 Comment text*/09 useful text'& @CRLF
$sText &= '10 useful text/*08 Comment text*/'& @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= @CRLF
$sText &= '/*09 Comment text*/11 useful text/*10 Comment text*/'& @CRLF
$sText &= '12 useful text'& @CRLF
$sText &= '/*11 Comment text*/13 useful text/*12 Comment text*/'& @CRLF
$sText &= '/*13 Comment text*/14 useful text/*14 Comment'& @CRLF
$sText &= 'text*/'& @CRLF

$sOld = $sText
$sOld = StringRegExpReplace($sOld, "/\*(?s).*?\*/", "") ; To delete comments of the type "/*[anything]*/".
$sOld = StringRegExpReplace($sOld, "(?m)^//.*?$", "") ; To delete lines of the type "//[anything]".
$sOld = StringRegExpReplace($sOld, "//.*?((?m)$)", "\0") ; To delete right parts of lines, starting from "//[anything]".

$sNew = $sText
$sNew = StringRegExpReplace($sNew, "//[^\v]*", "") ; удалить комент после //
$sNew = StringRegExpReplace($sNew, "(?s)/\*.*?\*/\v*?", "") ; удалить комент между /* и */
$sNew = StringRegExpReplace($sNew, "(\v+)", @CRLF) ; удалить пустые строки
$sNew = StringRegExpReplace($sNew, "(^\v+|\v+$)", '') ; удалить перенос строки в начале и конце текста

ConsoleWrite('----------Old----------'& @CRLF)
ConsoleWrite($sOld& @CRLF)
ConsoleWrite('----------New----------'& @CRLF)
ConsoleWrite($sNew& @CRLF)
ConsoleWrite('-----------------------'& @CRLF)
По крайней мере, эта последовательность регулярных выражений справляется с отредактированным текстом, на которой предыдущий скрипт опростоволосился бы, удалив важные части. Этот тоже неидеален с точки зрения универсальности, и мне изначально хотелось найти что-то иное, но для практического применения, вероятно, сойдёт. Во всяком случае, для целей дальнейшего парсинга. Мне в итоге удалось обойтись даже и собственным скриптом, в котором точно имеются ошибки, совмещая автоматическую работу с ручной и полуавтоматической.

С формальной точки зрения задача не требовала удалять те пустые строки, которые возникли не в результате чистки комментариев, в строках с которыми нет полезного кода, но это не проблема в случае, когда конечная цель - именно очистка от мусора комментариев перед парсингом. Если код поступил от работающих на MacOS или на Linux, то тоже понятно, как отредактировать скрипт. Лишь самую малость посложнее, если над одним текстом кода работали на компьютерах под разными операционными системами.

Короче говоря, вызов для идеального решения задачи остаётся, но больше для теоретической головоломки и для изучения граней возможностей регулярных выражений. А топик останется доступным для поисковых систем и вполне может пригодиться даже тем, кто искал подобное не только для применения в AutoIt.
 

RaZum

Знающий
Сообщения
78
Репутация
14
Возможно это лишняя информация, но заметил что отсутствует несколько вариантов включения комментариев в код. Например:
Нет продолжения формата "//". Этот комментарий можно переносить на следующую строку, если перед переносом поставить "\", и так до его отсутствия в последней строке комментария.
Отсутствует вариант когда в коде, в строковом значении (что в "..."), присутствуют совпадения с тегами комментариев (тот же web адрес).
 

Alecsis

Осваивающий
Сообщения
98
Репутация
41
Между прочим, RaZum «как с языка снял»…
вариант когда в коде, в строковом значении (что в "..."), присутствуют совпадения с тегами комментариев
а Oki ещё раньше опередил
что для идеального решения проще собственный парсер
Что-то мне подсказывает: аж DOS-овский Turbo C++ времён доблестной конторы Borland отлично обходился без рег-выражений. И что совсем характерно, компилил с гиперзвуковой скоростью. Стало быть, есть простор для изысканий :drinks:
 
  • Like
Реакции: Oki

RaZum

Знающий
Сообщения
78
Репутация
14
Некоторое моменты можно подсмотреть в редакторах с подсветкой синтаксиса
 
Верх