Удаление цветовых кодов ANSI из текстового потока

73

Изучение выхода из

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";'

в текстовом редакторе (например, vi) отображается следующее:

^[[37mABC
^[[0m

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

Следующее не работает

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' | perl -pe 's/\^\[\[37m//g' | perl -pe 's/\^\[\[0m//g'
user001
источник
Не ответ на вопрос, но вы также можете перенаправить выходные данные moreили less -Rкоторые могут интерпретировать escape-коды как цвет вместо текстового редактора.
тердон

Ответы:

98

Символы ^[[37mи ^[[0mявляются частью escape-последовательностей ANSI (коды CSI) . Смотрите также эти спецификации .

Использование GNU sed

sed 's/\x1b\[[0-9;]*m//g'
  • \x1b(или \x1B) является специальным символом escape
    ( sedне поддерживает альтернативы \eи \033)
  • \[ является вторым символом escape-последовательности
  • [0-9;]* это значение цвета (s) регулярное выражение
  • m последний символ escape-последовательности

⚠ На MacOS, по умолчанию sedкоманда не поддерживает специальные символы , такие как , \eкак указывал слм и steamer25 в комментариях. Используйте вместо этого, gsedчто вы можете установить с помощью brew install gnu-sed.

Пример с командной строкой OP :   (OP означает оригинальный постер)

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' | 
      sed 's/\x1b\[[0-9;]*m//g'

Том Хейл предлагает удалить все другие escape-последовательности, используя [a-zA-Z]вместо буквы, mспецифичной для escape-последовательности графического режима (цвета). Но [a-zA-Z]может быть слишком широким и может удалить слишком много. Михал Фаленски и Мигель Мота предлагают удалить только некоторые escape-последовательности, используя [mGKH]и [mGKF]соответственно. Бриттон Керин указывает, что Kтакже должен использоваться в дополнение к mудалению цветов из сообщения gccоб ошибке / предупреждении (не забудьте перенаправить gcc 2>&1 | sed...).

sed 's/\x1b\[[0-9;]*m//g'           # Remove color sequences only
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g'    # Remove all escape sequences
sed 's/\x1b\[[0-9;]*[mGKH]//g'      # Remove color and move sequences
sed 's/\x1b\[[0-9;]*[mGKF]//g'      # Remove color and move sequences
Last escape
sequence
character   Purpose
---------   -------------------------------
m           Graphics Rendition Mode (including Color)
G           Horizontal cursor move
K           Horizontal deletion
H           New cursor position
F           Move cursor to previous n lines

С помощью perl

Версия sedустановленной в некоторых операционных системах может быть ограничена (например, MacOS). Преимущество этой команды perlв том, что ее обычно проще устанавливать / обновлять в более операционных системах. Адам Кац предлагает использовать \e(так же, как \x1b) в PCRE .

Выберите свое регулярное выражение в зависимости от того, сколько команд вы хотите отфильтровать:

perl -pe 's/\e\[[0-9;]*m//g'          # Remove colors only
perl -pe 's/\e\[[0-9;]*[mG]//g'
perl -pe 's/\e\[[0-9;]*[mGKH]//g'
perl -pe 's/\e\[[0-9;]*[a-zA-Z]//g'
perl -pe 's/\e\[[0-9;]*m(?:\e\[K)?//g' # Adam Katz's trick

Пример с командной строкой OP:

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' \
      | perl -pe 's/\e\[[0-9;]*m//g'

использование

Как указано в комментарии Стюарта Кардалла , эта sedкомандная строка используется проектом Ultimate Nginx Bad Bot (1000 звезд) для очистки отчета по электронной почте ;-)

olibre
источник
2
Спасибо за sedкоманду и объяснение. :)
Redsandro
2
Некоторые цветовые коды (например, терминал Linux) содержат префикс, например, 1;31mтак что лучше добавьте его ;в регулярное выражение: cat colored.log | sed -r 's/\x1b\[[0-9;]*m//g'иначе они не будут удалены.
Redsandro
1
это здорово, используйте его в github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/blob/… для очистки отчета по электронной почте.
Стюарт Кардалл
2
Имейте в виду, что версия OSX sedне работает с показанным примером, gsedоднако версия работает.
ОДС
2
Больше контекста для комментария slm о OSX sed: он не поддерживает управляющие символы, такие как \ x1b. Например, stackoverflow.com/a/14881851/93345 . Вы можете получить команду gsed через brew install gnu-sed.
Steamer25
21

Я нашел лучший способ удаления последовательности побега. Проверь это:

perl -pe 's/\x1b\[[0-9;]*[mG]//g'

user204331
источник
2
В чем улучшение от принятого ответа ( superuser.com/a/380778/46794 )?
Blaisorblade
4
@Blaisorblade Это работает на OS X, тогда sed -rкак НЕ.
Б.В. Венгеров
10

Что отображается как ^[это не ^ и [; это символ ASCII ESC, созданный с помощью Escили Ctrl[( ^обозначение означает клавишу Ctrl).

ESC0x1B шестнадцатеричный или 033 восьмеричный, поэтому вы должны использовать \x1Bили \033в своих регулярных выражениях:

perl -pe 's/\033\[37m//g; s/\033[0m//g'

perl -pe 's/\033\[\d*(;\d*)*m//g'
grawity
источник
6

Если вы предпочитаете что-то простое, вы можете использовать модуль strip-ansi ( требуется Node.js ):

$ npm install --global strip-ansi-cli

Тогда используйте это так:

$ strip-ansi < colors.o

Или просто передайте строку:

$ strip-ansi '^[[37mABC^[[0m'
Синдре Сорхус
источник
Это бесполезное использование cat( UUOC ) - это должно быть возможно strip-ansi colors.oили по крайней мере strip-ansi < colors.o.
Скотт
1
@ Скотт Конечно, вы тоже можете strip-ansi < colors.o, но по опыту люди лучше знакомы с трубопроводами. Я обновил ответ.
Синдре Сорхус
хорошее простое решение
Penghe Geng
3

commandlinefu дает этот ответ, который отбрасывает цвета ANSI, а также команды перемещения:

sed "s,\x1B\[[0-9;]*[a-zA-Z],,g"

Для только цветов, вы хотите:

 sed "s,\x1B\[[0-9;]*m,,g"
Том Хейл
источник
3

Я считаю, что это авторитетное удаление всех escape-последовательностей ANSI :

perl -pe '
  s/\e\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]//g;
  s/\e[PX^_].*?\e\\//g;
  s/\e\][^\a]*(?:\a|\e\\)//g;
  s/\e[\[\]A-Z\\^_@]//g;'

(Обратите внимание , что PERL, как и многие другие языки (но не СЭД), принимает в \eкачестве экранирующего символа Esc, \x1bили с \033помощью кода, показанного в терминалах , как ^[. Я использую его здесь , потому что кажется более понятным.)

Эта команда perl, которую вы можете запустить все в одну строку, если хотите, содержит четыре замены:

Первый идет после последовательностей CSI (последовательности escape-кодов, начинающиеся с «Представителя управляющих последовательностей» Esc[, который охватывает гораздо больше, чем последовательности Select Graphic Rendition, которые составляют цветовые коды и другие текстовые декорации).

Вторая замена удаляет оставшиеся последовательности, которые включают в себя завершающие символы и оканчиваются на ST (терминатор строки, Esc\). Третья замена это то же самое , но также позволяет команд операционной системы последовательности , чтобы закончить с BEL ( \x07, \007часто \a).

Четвертая замена удаляет оставшиеся побеги.

Также рассмотрите возможность удаления других символов ASCII нулевой ширины, таких как BEL и других более неясных управляющих символов C0 и C1 . Я использую s/[\x00-\x1f\x7f-\x9f\xad]+//g, который также включает Delete и Soft Hyphen . Это исключает более длинные закодированные символы Unicode с нулевой шириной, но я считаю, что это является исчерпывающим для ASCII (Unicode \x00- \xff). Если вы сделаете это, удалите эти последние, поскольку они могут быть включены в более длинные последовательности.

Адам Кац
источник
2

«Ответ» на вопрос не сработал для меня, поэтому я вместо этого создал это регулярное выражение для удаления escape-последовательностей, создаваемых модулем perl Term :: ANSIColor.

cat colors.o | perl -pe 's/\x1b\[[^m]+m//g;

Регулярное выражение Grawity должно работать нормально, но использование + тоже работает нормально.

castl3bravo
источник
4
(1) Что вы подразумеваете под The "answered" question? Вы имеете в виду принятый ответ? (2) Эта команда не работает - она ​​даже не выполняется - потому что имеет непревзойденную (несбалансированную) кавычку. (3) Это бесполезное использование cat( UUOC ) - это должно быть возможно сделать . (4) Кто-нибудь говорил что-нибудь о кодах в файле? perl -pe command colors.o.o
Скотт
1

«tput sgr0» оставил этот управляющий символ ^ (B ^ [
Вот модифицированная версия, чтобы позаботиться об этом.

perl -pe 's/\e[\[\(][0-9;]*[mGKFB]//g' logfile.log
GustafAnkarloo
источник
Спасибо за это ... это помогло мне избавиться от того tput sgr0, от чего другие решения, кажется, никогда не смогут избавиться.
TxAG98
0

У меня была похожая проблема с удалением символов, добавленных из сбора интерактивного верхнего вывода через замазку, и это помогло:

cat putty1.log | perl -pe 's/\x1b.*?[mGKH]//g'
Михал Фаленский
источник
3
Это бесполезное использование cat( UUOC ) - это должно быть возможно сделать . perl -pe command putty1.log
Скотт
0

Это то, что у меня сработало (проверено на Mac OS X)

perl -pe 's/\[[0-9;]*[mGKF]//g'
Мигель Мота
источник