
Есть ли утилита типа grep, которая позволит мне выполнять поиск grep с логическими операторами. Я хочу иметь возможность свободно вкладывать и комбинировать логические конструкции. Например, должно быть возможно что-то вроде этого:
grep (term1 && term2) || (term1 && (term3 xor term4)) *
Я понимаю, что это можно сделать с помощью vanilla grep и дополнительных скриптов bash, но моя цель — избежать необходимости делать это.
решение1
Существует множество способов использования grep
логических операторов.
Использование нескольких
-e
вариантов соответствует всему, что соответствует любому из шаблонов, даваяИЛИоперация.Пример:
grep -e pattern1 -e pattern2 filename
В расширенных регулярных выражениях (
grep -E
) можно использовать|
для объединения нескольких шаблонов с помощьюИЛИоперация.Пример:
grep -E 'pattern1|pattern2' filename
grep -v
может имитироватьНЕТоперация.Здесь нетИоператор в
grep
, но вы можете смоделировать методом перебораИиспользуя несколько шаблонов с|
.Пример :
grep -E 'pattern1.*pattern2|pattern2.*pattern1' filename
Приведенный выше пример будет соответствовать всем строкам, которые содержат оба шаблон1ишаблон2в любом порядке. Это становится очень некрасивым, если нужно объединить больше шаблонов.
решение2
С awk
, как и с perl
, вам придется заключать термины в //
, но это можно сделать:
awk '(/term1/ && /term2/) || (/term1/ && xor(/term3/, /term4/))'
Обратите внимание, что xor()
нестандартное расширение GNU является битовым xor
, а не логическим. Здесь это нормально, поскольку они /regex/
всегда возвращают только 0 или 1.
С другими awk
вы можете определить логическую xor()
функцию:
function xor(a, b) {
return (a || b && ! (a && b))
}
Или
function xor(a, b) {
return ((a && !b) || (b && !a))
}
решение3
Вы можете использовать Perl:
perl -wne 'print if (/term1/ && /term2/) || (/term1/ && (/term3/ xor /term4/))'
Гдепереключателиследующие:
-w turns on warnings
-n runs perl against each line of input (looping)
-e executes perl passed in the command line
решение4
Я использую цепочку grep
команд для достижения логического И:
grep expr1 filename | grep expr2
Я считаю, что это довольно просто, Unix-подобно и элегантно.
Затем вы можете объединить (как подробно объяснил @Tushi) с -E
опцией для ИЛИ и -v
для отрицания.
Ваш конкретный пример довольно неприятен и, вероятно, выиграл бы от использования более мощной утилиты (см. ответ @muru).