24

Я пытаюсь построить поиск grep, который ищет термин, но исключает строки, имеющие второй термин. Я хотел использовать несколько опций -e "pattern" , но это не сработало.

Вот пример команды, которую я пробовал, и сгенерированного сообщения об ошибке.

grep -i -E "search term" -ev "exclude term"
grep: exclude term: No such file or directory

Мне кажется, что -v применяется ко всем условиям поиска / шаблонам. Поскольку это выполняется, но не включает search term в результаты.

grep -i -E "search term" -ve "exclude term"

4 ответа4

39

Чтобы и выражения с grep вам нужно два вызова:

grep -Ei "search term" | grep -Eiv "exclude term"

Если искомые термины не являются регулярными выражениями, используйте фиксированное сопоставление строк (-F), что быстрее:

grep -F "search term" | grep -Fv "exclude term"
12

Если не вызывать grep дважды, я могу придумать только один способ сделать это. Он включает в себя Perl-совместимые регулярные выражения (PCRE) и некоторые довольно хакерские утверждения.

Для поиска foo, исключая совпадения, содержащие строку, вы можете использовать:

grep -P '(?=^((?!bar).)*$)foo'

Вот как это работает:

  • (?!bar) соответствует всему, что не является баром, не потребляя символы из строки. Потом . потребляет один символ.

  • ^((?!bar).)* повторяет вышеизложенное с начала строки (^) до ее конца ($). Он потерпит неудачу, если в любой заданной точке встретится bar , так как (?!bar) не будет совпадать.

  • (?=^((?!bar).)*$) гарантирует, что строка соответствует предыдущему шаблону, не потребляя символы из строки.

  • foo ищет foo как обычно.

Я нашел этот хак в регулярном выражении, чтобы соответствовать строке, не содержащей слова?, В ответе Барта Киерса вы можете найти гораздо более подробное объяснение того, как работает отрицательный прогноз.

8

Если вы хотите сделать это за один проход, вы можете использовать awk вместо grep.

Формат:

echo "some text" | awk '/pattern to match/ && !/pattern to exclude/'

Примеры:

  • echo "hello there" | awk '/hello/ && !/there/'

Ничего не возвращает

  • echo "hello thre" | awk '/hello/ && !/there/'

Возвращает: привет три

  • echo "hllo there" | awk '/hello/ && !/there/'

Ничего не возвращает

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

Примеры:

  • echo "hello thre" | awk '(/hello/ || /hi/) && !/there/'

Возвращает: привет три

  • echo "hi thre" | awk '(/hello/ || /hi/) && !/there/'

Возвращает: привет три

  • echo "hello there" | awk '(/hello/ || /hi/) && !/there/'

Ничего не возвращает

  • echo "hi there" | awk '(/hello/ || /hi/) && !/there/'

Ничего не возвращает

1

Из моих экспериментов не имеет особого значения, если вы передадите свои исключающие условия через grep или sed . Sed имеет некоторые другие полезные функции замены текста, которые я часто использую, чтобы лучше фильтровать выход файлов журнала. Поэтому я собираюсь использовать sed, так как я объединяю довольно много фильтров на sed.

wc /var/log/tomcat/tomcat.2013-01-14.log.1 
  1851725

 /usr/bin/time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/login OK/d" -e "/Login expired/d" | wc
24.05user 0.15system 0:25.27elapsed 95%CPU (0avgtext+0avgdata 3504maxresident)k
0inputs+0outputs (0major+246minor)pagefaults 0swaps
   5614   91168 1186298

 /usr/bin/time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/login OK/d" -e "/Login expired/d" | wc
23.50user 0.16system 0:24.48elapsed 96%CPU (0avgtext+0avgdata 3504maxresident)k
0inputs+0outputs (0major+246minor)pagefaults 0swaps
   5614   91168 1186298

 /usr/bin/time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "login OK" -e "Login expired" | wc
23.08user 0.14system 0:23.55elapsed 98%CPU (0avgtext+0avgdata 3504maxresident)k
0inputs+0outputs (0major+246minor)pagefaults 0swaps
   5614   91168 1186298

 /usr/bin/time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "login OK" -e "Login expired" | wc
23.50user 0.15system 0:25.27elapsed 93%CPU (0avgtext+0avgdata 3488maxresident)k
0inputs+0outputs (0major+245minor)pagefaults 0swaps
   5614   91168 1186298

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .