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

мой код анализирует некоторые строки в файле журнала.

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

я довольно хорошо разбираюсь в регулярных выражениях. но я не могу понять это.

проблема: я хочу захватить любую строку, которая не содержит слова error или warn. если только это не первая часть записи журнала, заключенная в квадратные скобки.

до сих пор я пробовал что-то вроде этого:

(((?:abc|cba)\s+.*(?!\[?(?!error|warn)\]?).*)|((abc|cba)\s+\[(error|warn)\]\s+(.*)))

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

группа захвата 2:

abc [error] message
cba [error] message
cba [warn] message

группа захвата 1:

abc something random
cba i dont know

не захватывать:

abc some [error] message
cba some [warn] message

задача на более простом английском языке; Я хочу получить любую строку, начинающуюся с abc или cba. группа захвата 1 должна захватить строку, если в ней нет [error] или [warn]. и группа захвата 2 должна получить его, только если [error] или [warn] являются первой частью записи (после abc или cba)


person Inbar Rose    schedule 09.10.2012    source источник
comment
Итак, регулярное выражение должно работать только в 1 строке? Как вы передаете строки одну за другой регулярному выражению для проверки?   -  person nhahtdh    schedule 09.10.2012
comment
@nhahtdh каждая строка файла анализируется регулярным выражением. 1 на 1. да.   -  person Inbar Rose    schedule 09.10.2012


Ответы (1)


Это должно помочь:

^(?:abc|cba)(?:(?!.*(?:\[error\]|\[warn\]))|\s*(?:\[error\]|\[warn\])).*$

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

Сначала я проверяю abc и cba, начиная линию.

Тогда 2 случая:

  • Ни [error], ни [warn] не появляются нигде в строке: (?!.*(?:\[error\]|\[warn\])) (?: не очень важна, просто не захватывающая группа).
  • Или [error] или [warn] следуют сразу после abc и cba: \s*(?:\[error\]|\[warn\]). Обратите внимание, что вы можете изменить \s* на \s+, так как текущее регулярное выражение будет соответствовать abc[error].

Тогда остальное мне безразлично .*, но оно там должно быть, так как я использовал $. Я не совсем уверен в Python: проверьте, можете ли вы удалить .*$ часть регулярного выражения.

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

person nhahtdh    schedule 09.10.2012
comment
спасибо. ваше решение помогло мне найти то, что сработало для меня. если интересно, я в настоящее время использую: ((?:abc|cba)(?!.*(?:\[(?:error|warn)\]).*).*)|((abc|cba)\s+\[(error|warn)\]\s+(.*)) - вещь, которая заставила его работать, заключалась в том, чтобы включить .* внутри отрицательного прогноза ((?!)) :) regexr.com?32db0 - person Inbar Rose; 09.10.2012
comment
@InbarRose: я не уверен, какую функцию вы используете, но проверьте этот случай: "sfdkjsfhk abc [error] askdjhaksd" - следует отклонить. - person nhahtdh; 09.10.2012
comment
да - я знаю, но это только часть основного регулярного выражения. что случаи разные вещи. Спасибо за вашу заботу. я просто пытался выяснить, как именно игнорировать строки с этим конкретным форматом после всей остальной моей работы. - также - я связал неправильное регулярное выражение - это должно быть regexr.com?32db3 - person Inbar Rose; 09.10.2012