Фильтровать вывод команды по цвету

13

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

Как я могу отфильтровать не красный текст?

псевдокод:

dolongtask | grep -color red

редактировать

Команда выводит другие цвета , а также и мне нужно , чтобы иметь возможность фильтровать вне весь текст, не красного цвета. Также окраска текста многострочная.

km6zla
источник
1
Я прошу прощения за то, что спросил очевидное - но все выходные включены >&1? Я имею в виду, красные вещи не исчезнут, если ты 2>/dev/null, верно?
mikeserv

Ответы:

15

Переключение цвета осуществляется с помощью escape-последовательностей, встроенных в текст. Программы всегда выдают escape-последовательности ANSI , потому что это то, что в настоящее время поддерживают практически все терминалы.

Экранирующая последовательность для переключения цвета переднего плана на красный - это \e[31mгде \eэкранирующий символ (восьмеричный 033, шестнадцатеричный 1b, также известный как ESC, ^[и различные другие обозначения). Числа в диапазоне 30–39 задают цвет переднего плана; другие числа устанавливают разные атрибуты. \e[0mсбрасывает все атрибуты к их значению по умолчанию. Запустите, cat -vчтобы проверить, что печатает программа, она может использовать какой-либо вариант, например, \e[0;31mсначала сбросить все атрибуты или \e[3;31также включить курсив (который не поддерживают многие терминалы).

В ksh, bash или zsh вы можете использовать $'…'для включения обратной кавычки внутри кавычек, что позволяет вам печатать, $'\e'чтобы получить escape-символ. Обратите внимание, что вам придется удваивать обратную косую черту, которую вы хотите передать grep. В /bin/sh, вы можете использовать "$(printf \\e)"или ввести буквальный escape-символ.

С GNU grep -oвариантом, следующий фрагмент кода фильтрует красный текст, при условии , что она начинается с последовательностью побега \e[31m, заканчивается либо с \e[0mили \e[30mна одной и ту же линию, и содержат не вложенную последовательность.

grep -Eo $'\e\\[31m[^\e]*\e\\[[03]?m'

Следующий awkфрагмент извлекает красный текст, даже если он многострочный.

awk -v RS='\033' '
    match($0, /^\[[0-9;]*m/) {
        color = ";" substr($0, 2, RLENGTH-2) ";";
        $0 = substr($0, RLENGTH+1);
        gsub(/(^|;)0*[^03;][0-9]*($|;)/, ";", color);
        red = (color ~ /1;*$/)
    }
    red'

Вот вариант, который сохраняет команды изменения цвета, которые могут быть полезны, если вы фильтруете несколько цветов (здесь красный и пурпурный).

awk -v RS='\033' '
    match($0, /^\[[0-9;]*m/) {
        color = ";" substr($0, 2, RLENGTH-2) ";";
        printf "\033%s", substr($0, 1, RLENGTH);
        $0 = substr($0, RLENGTH+1);
        gsub(/(^|;)0*[^03;][0-9]*($|;)/, ";", color);
        desired = (color ~ /[15];*$/)
    }
    desired'
Жиль "ТАК - прекрати быть злым"
источник
Решение awk сработало для меня. Любой способ сохранить цвет на выходе?
km6zla
@ ogc-nick Вы хотите полностью красный вывод? printf '\e[31m'; awk …; printf '\e[0m'
Жиль "ТАК ... перестать быть злым"
Просто для любого цвета, который я фильтрую, чтобы сохранить на выходе.
km6zla
@ ogc-nick Смотрите мои изменения.
Жиль "ТАК - перестань быть злым"
6

Вы можете использовать grep look для управляющих символов, некоторые из которых отвечают за создание красивых цветов на терминале.

dolongtask | grep '[[:cntrl:]]'

Например, это отображает красный «тест» в grep, который находит его, потому что он окружен управляющими символами:

$ echo -e '\033[00;31mtest\033[00m' | grep --color=none '[[:cntrl:]]'
test     <-- in red

--color=none просто для того, чтобы убедиться, что grep не применяет свою собственную раскраску к согласованному выводу, но печатает всю строку точно, так что управляющие символы будут интерпретироваться оболочкой.

savanto
источник
Ницца. Интересно, можно ли пойти дальше и сделать что-то подобное grep -E $'\033\[0?[01];31m.+?\033\[0?0m'или специально grep -Po '\033\[0?[01]+;31m\K.+?(?=\033\[0?0m)'проверить на красный?
Steeldriver
Я начал придумывать регулярные выражения, подобные тем, которые вы предлагаете, но прежде чем я смог заставить их работать, я наткнулся на [[:cntrl:]]. Я проверил ваши, и они работают на меня, т.е. соответствие красного цвета и не совпадение с другими цветами.
Саванто
Прекрасно работает, но подойдет любой цвет. Я не упомянул об этом в вопросе, но многие другие цвета также выводятся, и я просто хочу увидеть красный материал. +1 за простой и рабочий код.
km6zla