Сохранить окраску после передачи grep в grep

145

В разделе « Сохранить ls-раскраску после grep'ing» есть аналогичный вопрос, но меня раздражает, что если вы передадите цветной вывод grep в другой grep, раскраска не сохраняется.

В качестве примера grep --color WORD * | grep -v AVOIDне сохраняет цвет первого вывода. Но для меня ls | grep FILEцвет сохраняется, почему разница?

Цитракс
источник
2
Этот вопрос, кажется, не по теме, потому что он касается использования команд Unix, принадлежит unix.stackexchange.com
Raptor

Ответы:

166

grepиногда отключает цветной вывод, например, при записи в канал. Вы можете изменить это поведение с помощьюgrep --color=always

Правильная командная строка будет

grep --color=always WORD * | grep -v AVOID

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

alias cgrep="grep --color=always"

к вашему, .bashrcнапример, и используйте cgrepкак цветной grep. При переопределении grepвы можете столкнуться с проблемами со сценариями, которые зависят от конкретного вывода grepи не любят escape-код ascii.

Отто Аллмендингер
источник
5
Это решение работает только при определенных удачных обстоятельствах. См. Ответ Андерсонвома ниже.
studog
В моем случае (Ubuntu) у меня уже был псевдоним grep. alias grep='grep --color=autoпоэтому мне нужно просто изменить мой, ~/.bashrcгде он был определен в первую очередь.
sobi3ch
1
Не работает для меня - аналогично этому сценарию stackoverflow.com/a/7640077/248616
Nam G VU
Эта прекрасная творческая идея проста и работает stackoverflow.com/a/36288791/248616
Nam G VU
вопрос в том, как сделать так, чтобы второй grep не подавлял цвет первого. Это не ответ на этот вопрос.
johannes_lalala
74

Небольшой совет:

При использовании grep --color=alwaysфактические строки, передаваемые в следующий канал, будут изменены. Это может привести к следующей ситуации:

$ grep --color=always -e '1' * | grep -ve '12'
11
12
13

Несмотря на то, что параметр -ve '12'должен исключать среднюю линию, этого не произойдет, потому что между 1и есть цветные символы 2.

Андерсонвом
источник
Если вы используете --color=auto, то он должен уловить тот факт, что вы подключаете его где-то еще, и полностью подавить цвета, но это как бы нарушает цель. Если вам все еще нужны цветные результаты, я думаю, вы можете снова использовать grep при последнем использовании канала --color.
andersonvom
3
По крайней мере, в Mac OS X раскраска последней трубы, как предполагает @andersonvom, не работает. Не знаю почему; может это раскрашивание исключенного узора? --color=alwaysдействительно работает, я полагаю, с оговорками, указанными выше.
user766353
4
В выражении дважды должен быть один и тот же шаблон grep. Я только что протестировал это на Mac: http://i.imgur.com/BhmwAlF.png
andersonvom
10

Просто повторите ту же команду grep в конце конвейера.
grep WORD * | grep -v AVOID | grep -v AVOID2 | grep WORD

Alex
источник
2
Разве реверсирование команд не дало бы того же результата? grep -v AVOID * | grep WORD
Брайдон Гибсон
@BrydonGibson, наверное, но это был пример, показывающий, что он работает для любого количества команд,
Alex
2

Существующие ответы относятся только к случаю, когда команда ПЕРВАЯ grep(по запросу OP, но эта проблема возникает и в других ситуациях).

Более общий ответ

Основная проблема в том, что команда BEFORE | grepпытается быть «умной», отключая цвет, когда понимает, что вывод идет в канал. Обычно это именно то, что вам нужно, чтобы escape-коды ANSI не мешали вашей последующей программе.

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

Git: используйте -c color.status = always

git -c color.status=always status | grep -v .DS_Store

Примечание: -cопция должна идти ДО подкоманды status.

Другие

(это сообщение вики сообщества, так что не стесняйтесь добавлять свои)

оборота Шридхара Сарнобата
источник