Бесконечный цикл с Regex

Мы используем инструмент миграции RoundhousE в одном из наших проектов, более ориентированных на SQL. Я наткнулся на очень странную ошибку

Определенный скрипт функции SQL (к сожалению, я не могу предоставить скрипт, потому что он принадлежит моему клиенту), метод Replace RegEx никогда не возвращается

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

(?<KEEP1>^(?:[\s\t])*(?:-{2}).*$)|(?<KEEP1>/{1}\*{1}[\S\s]*?\*{1}/{1})|(?<KEEP1>'{1}(?:[^']|\n[^'])*?'{1})|(?<KEEP1>\s)(?<BATCHSPLITTER>GO)(?<KEEP2>\s)|(?<KEEP1>\s)(?<BATCHSPLITTER>GO)(?<KEEP2>$)

Строка кода в RounhousE, которая никогда не возвращается

string sql_statement_scrubbed = regex_replace.Replace(sql_to_run, match => evaluate_and_replace_batch_split_items(match, regex_replace));

Проблема не в делегате evaluate_and_replace_batch_split_items его в фактическом методе regex.Replace, я попробовал регулярное выражение в простом инструменте регулярных выражений, и он также зависает. Может быть, кто-то здесь, гуру на RegEx, может увидеть, в чем проблема?

редактировать: если я удаляю ' (Апостроф) из этого комментария SQL -- If no previous, don't report revisedэто работает, но дело не только в том, что он должен быть комбинацией другого текста в скрипте, потому что эта строка работает сама по себе

1 ответ

Решение

Обычно, когда регулярному выражению требуется бесконечное соответствие (или, что более вероятно, выясняется, что оно не соответствует), это происходит из-за катастрофического обратного отслеживания. В вашем регулярном выражении есть несколько случаев, которые могут быть подвержены этому, в зависимости от того, как выглядит ваш ввод. Я взял ваше регулярное выражение и немного его очистил, удалив множество ненужных квантификаторов и чередований. Это регулярное выражение:

(?<KEEP1>^\s*--.*$)|(?<KEEP1>/\*[\S\s]*?\*/)|(?<KEEP1>'[^']*')|(?<KEEP1>\s)(?<BATCHSPLITTER>GO)(?<KEEP2>\s|$)

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

Для обработки сбежавших апострофов внутри строки ('It\'s something else!') правильно, вам нужно изменить регулярное выражение:

(?<KEEP1>^\s*--.*$)|(?<KEEP1>/\*[\S\s]*?\*/)|(?<KEEP1>'(?:\\.|[^'\\])*')|(?<KEEP1>\s)(?<BATCHSPLITTER>GO)(?<KEEP2>\s|$)
Другие вопросы по тегам