Регулярное выражение для соответствия только тем строкам кода, которые не закомментированы - PullRequest
1 голос
/ 02 апреля 2020

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

Например:

// Messagebox(a,b,c, mb_ok);
Messagebox(a,b,c, mb_ok|mb_taskmodal);
Messagebox(a,b,c, mb_ok);

У меня есть регулярное выражение для соответствия 1 и 3. Теперь я хочу отфильтровать и закомментированные строки. Конечное регулярное выражение должно соответствовать только строке 3. Это возможно только с регулярным выражением?

Регулярное выражение используется для соответствия 1 и 3: https://regexr.com/51mjh

(MessageBox\(\s*.*,.*,.*,\s*)(?!.*MB_TASKMODAL)

Условия:

а. MessageBox API, который принимает 4 параметра.

b. Последний параметр не должен содержать MB_TASKMODAL.

c. Строка не должна быть закомментирована.

Ответы [ 2 ]

1 голос
/ 02 апреля 2020

Вы избегаете // -комментированных строк с:

^(?!\/\/).*

Объяснение (также в regex101 ):

  • ^ Начало строка
  • (?!\/\/) Не буквальное ведение // (это отрицательный прогноз )
  • .* Любое число любого символа (для пропуска пустых строк, измените на .+)

Если вы беспокоитесь о пробелах, вместо этого используйте ^(?!\s*\/\/).*.


Теперь, чтобы перейти к части о сопоставлении только строки тройка.

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

^(?!\/\/).*\bMessagebox\((?!.*\bmb_taskmodal\b).*

Здесь есть вышеупомянутое исключение для закомментированных строк, а затем он соответствует Messagebox( после несловесного символа (или ничего) , за исключением , если за ним в конечном итоге следует mb_taskmodal как полное слово, а затем все остальное.

Я использую \b немного здесь. Это означает, что ровно одна сторона (до или после \b) имеет символ слова (букву, цифру или знак подчеркивания), а другая сторона не имеет слова. «B» означает «[слово] граница». Экранированные несловарные символы всегда являются литералами, поэтому \( и \/ являются литералами ( и / соответственно.

Обратите внимание, что это регулярное выражение все равно будет соответствовать Messagebox(a,b,c, mb_ok); // |mb_taskmodal);. Устранение этого является нетривиальным, поскольку индикатор встроенного комментария состоит из двух символов. Я тоже могу ответить, но, надеюсь, вам это не нужно.


Решения с помощью grep:

$ grep -v '^//' FILENAME                            # discard comments
$ grep -v '^//' FILENAME |grep -vFw 'mb_taskmodal'  # also discard mb_taskmodal

Флаг -v Grep инвертирует совпадение. -F отключает регулярные выражения и использует простое совпадение текста (быстрее), а -w требует наличия границ слов вокруг запроса (так же, как \bmb_taskmodal\b при условии GNU grep без -F).


Решение для фильтрации комментариев в расширенном регулярном выражении (ERE) (без поиска):

(Если вы используете grep, рассмотрите grep -v '^//' FILENAME)

^(.?$|[^\/]{2}|[^\/]\/|\/[^\/]).*

Объяснение (также в regex101 ):

  • ^ Начало строки
  • (…) Группа захвата (PCRE может запретить захват с помощью (?:…) вместо), содержащая либо
    • Чередование один
      • .? Любой символ, ноль или один раз (измените на ..?, чтобы пропустить пустые строки)
      • $ Конец строки
    • Чередование два
      • [^\/]{2} Любой символ, кроме /, дважды
    • Чередование три
      • [^\/] Любой символ, кроме /
      • \/ Литерал /
    • Чередование четыре (порядок поменялся местами)
      • * 111 6 * Литерал /
      • [^\/] Любой символ, кроме /
  • .* Любое число любого символа ( включая ноль, требуется для чередования 1)

Это будет соответствовать пустой строке или строке, например / или j, или более длинной строке без комментариев.

0 голосов
/ 02 апреля 2020

Вы можете немного сократить шаблон и использовать класс отрицательных символов [^,], соответствующий любому символу, кроме запятой, с последующим соответствием запятой. Если вы группируете эту часть, ее можно повторить 3 раза с помощью квантификатора {3}

Если группа захвата является единственным совпадением, вы также можете опустить ее.

Как уже отвечали, вы можно использовать отрицательный запрос, чтобы проверить, начинается ли строка с //, и, возможно, добавить \s*, если перед ним могут быть возможные символы пробела, или использовать [\S\r\n]* для сопоставления символов пробела без символов новой строки.

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

^(?![^\S\r\n]*//)[^\S\r\n]*MessageBox\(\s*(?:[^,]*,){3}\s*(?!.*MB_TASKMODAL)

Regex demo

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...