Grep регулярное выражение НЕ содержит строку

182

Я передаю список шаблонов регулярных выражений grepдля сравнения с файлом системного журнала . Они обычно соответствуют IP-адресу и записи в журнале;

grep "1\.2\.3\.4.*Has exploded" syslog.log

Это просто список шаблонов, таких как "1\.2\.3\.4.*Has exploded"часть, которую я передаю в цикле, поэтому я не могу передать, например, «-v».

Я запутался, пытаясь сделать обратное вышесказанному, строки НЕ совпадают с определенным IP-адресом и ошибкой, поэтому «! 1.2.3.4. * Разорвал» будет сопоставлять строки системного журнала для всего, кроме 1.2.3.4, сообщая мне, что он взорвался , Я должен иметь возможность включить IP, чтобы не совпадать.

Я видел различные подобные посты в StackOverflor, однако они используют шаблоны регулярных выражений, с которыми я не могу работать grep. Кто-нибудь может привести рабочий пример для grepпожалуйста?

ОБНОВЛЕНИЕ: Это происходит в сценарии, как это;

patterns[1]="1\.2\.3\.4.*Has exploded"
patterns[2]="5\.6\.7\.8.*Has died"
patterns[3]="\!9\.10\.11\.12.*Has exploded"

for i in {1..3}
do
 grep "${patterns[$i]}" logfile.log
done
jwbensley
источник
Вы хотите сказать, что иногда хотите сопоставить шаблон, но в других случаях хотите сопоставить все, кроме определенного шаблона? (это кажется странным требованием, но неважно). В таком случае, почему бы вам не перебрать два разных списка шаблонов?
beerbajay
Ну, я не очень хорошо осведомлен о регулярных выражениях; Я не хочу использовать grep для слова «Has Exploded», потому что я не хочу знать об этом для каждого регистрирующего устройства, поэтому могу ли я как-то использовать grep для слова «Has Exploded» и! 9.10.11.12 в одном выражении?
Jwbensley
Если вы абсолютно обязаны сделать это в одном утверждении, негативные взгляды - это путь, как предлагает Нейл. Смотрите мой комментарий там.
beerbajay
Используйте соответствие регулярному выражению в стиле PCRE и отрицательное прогнозное утверждение в соответствии с ответом @Neil: patterns[3]="\!9\.10\.11\.12.*Has exploded"изменения patterns[3]="(?<!9\.10\.11\.12).*Has exploded"иgrep "${patterns[$i]}" logfile.log изменений в grep -P "${patterns[$i]}" logfile.logPCRE по умолчанию предполагается большее количество метасимволов, поэтому, возможно, придется удалить некоторые экранированные из других соответствующих выражений.
Codex24

Ответы:

342

grepсоответствует, grep -vделает обратное. Если вам нужно «соответствовать A, но не B», вы обычно используете трубы:

grep "${PATT}" file | grep -v "${NOTPATT}"
beerbajay
источник
Как я уже говорил, это происходит в середине цикла, и я просто передаю PATTERN в grep, поэтому я не могу использовать «-v», как я уже упоминал. Я просто зацикливаю список шаблонов и перехожу к grep.
jwbensley
1
Вы действительно можете использовать, -vи вы можете использовать его в цикле. Возможно, вам нужно быть более точным в отношении ваших ограничений, или, возможно, у вас неправильное представление о том, как должен работать ваш скрипт. Попробуйте опубликовать код.
beerbajay
Спасибо beerbajay, я добавил код, вырезанный в оригинальном сообщении, чтобы дать некоторый контекст. Вы понимаете, что я имею в виду сейчас?
jwbensley
Этот ответ не совсем правильный, но вы в значительной степени написали beerbajay, мне нужно было переосмыслить цикл и использовать -v в конце. Спасибо за указатель;)
jwbensley
1
Но что, если A состоит из B? Другими словами, что если я хочу сопоставить строки без A и строки с AB? Труба не будет работать.
Павамой
15
(?<!1\.2\.3\.4).*Has exploded

Вам нужно запустить это с -P, чтобы иметь отрицательный lookbehind (регулярное выражение Perl), поэтому команда:

grep -P '(?<!1\.2\.3\.4).*Has exploded' test.log

Попробуй это. Он использует отрицательный взгляд назад, чтобы игнорировать строку, если ей предшествует 1.2.3.4. Надеюсь, это поможет!

Нил
источник
1
Я уверен, что grepэто не поддерживает lookaround. Если вы не используете Gnu grepи не используете --Pпараметр, чтобы он использовал механизм PCRE.
Тим Питцкер,
Нет, grep не поддерживает этот тип регулярных выражений; $ grep -P (? <\! 1 \ .2 \ .3 \ .4) test.log -bash: синтаксическая ошибка рядом с неожиданным токеном `('
jwbensley
Вам нужно будет заключить в кавычки регулярное выражение, если оно содержит символы, которые будут интерпретироваться оболочкой.
beerbajay
правильное цитирование: grep -P '(?<!1\.2\.3\.4) Has exploded' test.logобратите внимание, что lookbehind работает только с символами, непосредственно предшествующими соответствующей части выражения, поэтому, если есть другие вещи между адресом и сообщением, например 1.2.3.4 FOO Has exploded, это не будет работать.
beerbajay
@TimPietzcker, очень наблюдательный. Я добавлю это к вопросу. Также, пожалуйста, обратите внимание, что .*после негативного взгляда есть след, поскольку в его примере это тоже есть, я думаю, что между ними может быть другой текст.
Нейл
2
patterns[1]="1\.2\.3\.4.*Has exploded"
patterns[2]="5\.6\.7\.8.*Has died"
patterns[3]="\!9\.10\.11\.12.*Has exploded"

for i in {1..3}
 do
grep "${patterns[$i]}" logfile.log
done

должен быть таким же, как

egrep "(1\.2\.3\.4.*Has exploded|5\.6\.7\.8.*Has died)" logfile.log | egrep -v "9\.10\.11\.12.*Has exploded"    
krecker
источник