Убрать комментарии из текста, за исключением символа комментария между кавычками - PullRequest
1 голос
/ 26 января 2012

Я пытаюсь построить регулярное выражение для удаления комментариев из файла конфигурации.Комментарии отмечены символом ;.Например:

; This is a comment line
keyword1 keyword2 ; comment
keyword3 "key ; word 4" ; comment

Моя сложность заключается в игнорировании символа комментария, когда он помещается между кавычками.

Есть идеи?

Ответы [ 5 ]

1 голос
/ 26 января 2012

Попытаться сопоставить точку с запятой можно только в том случае, если за ней следует четное количество кавычек:

;(?=(?:[^"]*"[^"]*")*[^"]*$).*

Обязательно используйте это регулярное выражение с параметром Singleline, в котором отключено опция Multiline включена на .

В Python:

>>> import re
>>> t = """; This is a comment line
... keyword1 keyword2 ; comment
... keyword3 "key ; word 4" ; comment"""
>>> regex = re.compile(';(?=(?:[^"]*"[^"]*")*[^"]*$).*', re.MULTILINE)
>>> regex.sub("", t)
'\nkeyword1 keyword2 \nkeyword3 "key ; word 4" '
0 голосов
/ 03 октября 2015

Я (несколько случайно) придумал рабочее регулярное выражение:

replace(/^((?:[^'";]*(?:'[^']*'|"[^"]*")?)*)[ \t]*;.*$/gm, '$1')

Я хотел:

  • удалить однострочные комментарии в начале или конце строки,
  • для использования одинарных и двойных кавычек,
  • возможность иметь только одну цитату в комментарии: , что ' s полезно (но также можно принять ")
    (поэтому совпадение по сбалансированному набору (четному числу) цитат после комментария-разделителя, как в ответ Тима Пицкера не подходит),
  • оставить комментарий-разделитель ; один в правильно (закрыто) в кавычках 'строки'
  • смешанный стиль цитирования
  • несколько строк в кавычках (и комментарии в / после комментариев)
  • гнездо одинарные / двойные кавычки в соотв. двойные / одинарные кавычки 'строки'
  • данные для работы подобны действительным ini-файлам (или сборкам), если они не содержат экранированных кавычек или литералов регулярных выражений и т. Д.

Отсутствие оглядки на javascript Я подумал, что может быть идеей не сопоставлять комментарии (и заменить их ''), , но сопоставить данные, предшествующие комментарию и затем замените данные полного совпадения на данные вспомогательного совпадения.
Можно представить эту концепцию построчно (поэтому замените полную строку соответствием, тем самым «потеряв» комментарий), НО многострочный параметр, похоже, работает не совсем так (при минимум в браузере).

[^'";]* начинает есть любые символы из 'start', которые не '";.
(Совершенно нелогично (для меня), [^'";\r\n]* будет не работать.)

(?:'[^']*'|"[^"]*")? - это группа без захвата, соответствующая нулю или одному набору quote any chars quote (?:(['"])[^\2]*\2)? в /^((?:[^'";]*(?:(['"])[^\2]*\2)?)*)[ \t]*;.*$/gm или
(?:(['"])[^\2\r\n]*\2)? в /^((?:[^'";]*(?:(['"])[^\2\r\n]*\2)?)*)[ \t]*;.*$/gm (хотя и таинственно лучше) делать , а не работу (разбито на db 'WDVPIVAlQEFQ;WzRcU',"hi;hi",0xfe,"'as), но не добавление еще одной группы захвата для повторного использования в матче - это хорошо, так как они идут с штрафы в любом случае).

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

Это оставляет нам [ \t]*;.*, который «просто» соответствует нулю или нескольким пробелам и символам табуляции, за которыми следует точка с запятой, за которой следует ноль или более символов, которые не являются новой строкой. Обратите внимание, что ; не является обязательным !!!

Чтобы получить лучшее представление о том, как это (многострочный параметр) работает, нажмите кнопку exp в демонстрационном примере ниже.

function demo(){
  var elms=document.getElementsByTagName('textarea');
  var str=elms[0].value;
  elms[1].value=str.replace( /^((?:[^'";]*(?:'[^']*'|"[^"]*")?)*)[ \t]*;.*$/gm
                           , '$1'
                           )
                   .replace( /[ \t]*$/gm, ''); //optional trim
}


function demo_exp(){
  var elms=document.getElementsByTagName('textarea');
  var str=elms[0].value;
  elms[1].value=str.replace( /^((?:[^'";]*(?:'[^']*'|"[^"]*")?)*)[ \t]*;.*$/gm
                           , '**S**$1**E**'  //to see start and end of match.
                           );
}
<textarea  style="width:98%;height:150px" onscroll="this.nextSibling.scrollTop=this.scrollTop;">
; This is a comment line
keyword1 keyword2 ; comment
keyword3 "key ; word 4" ; comment

  
"Text; in" and between "quotes; plus" semicolons; this is the comment
  
  ; This is a comment line
  keyword1 keyword2 ; comment
  keyword3 'key ; word 4' ; comment and one quote ' ;see it?
  
_b64decode:
        db    0x83,0xc6,0x3A ; add   si, b64decode_end - _b64decode ;39
        push  'a'   
        pop   di 
  
        cmp   byte [si], 0x2B ; '+'


b64decode_end:
        ;append base64 data here
        ;terminate with printable character less than '+'
        db 'WDVPIVAlQEFQ;WzRcU',"hi;hi",0xfe,"'as;df'" ;'haha"
;"end'
  
</textarea><textarea style="width:98%;height:150px" onscroll="this.previousSibling.scrollTop=this.scrollTop;">
result here
</textarea>
<br><button onclick="demo()">remove comments</button><button onclick="demo_exp()">exp</button>

Надеюсь, это поможет.

PS: Пожалуйста, прокомментируйте действительные примеры, если и где это может сломаться! Поскольку я в целом согласен (исходя из большого личного опыта), что невозможно надежно удалять комментарии с помощью регулярных выражений (особенно языков программирования более высокого уровня), моя интуиция все еще говорит, что это не может быть надежным доказательством. Однако я перебрасывал существующие данные и создавал «что-если» на них более 2 часов, но не смог их сломать (что я обычно очень хорошо умею).

0 голосов
/ 26 января 2012

Примерно так:

("[^"]*")*.*(;.*)

Сначала сопоставьте любое количество текста между кавычками, затем сопоставьте a;.Если;находится в кавычках, это будет совпадение первой группой, а не второй группой.

0 голосов
/ 26 января 2012

Вы можете использовать regexp, чтобы сначала вывести все строки, заменить их каким-нибудь заполнителем, а затем просто обрезать все \$.* и наконец заменить обратно строки:)

0 голосов
/ 26 января 2012

Нет регулярных выражений:)

$ grep -E -v '^;' input.txt
keyword1 keyword2 ; comment
keyword3 "key ; word 4" ; comment
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...