Удаление цветовых кодов ANSI из текстового потока
Изучение выхода из
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'
18 ответов
Персонажи ^[[37m
а также ^[[0m
являются частью последовательностей ANSI Escape (коды CSI).
Смотрите также полные спецификации.
С помощью sed
sed 's/\x1b\[[0-9;]*m//g'
\x1b
является специальным символом escape (так же, как\x1B
или же\033
)\[
является вторым символом escape-последовательности[0-9;]*
это значение цветаm
последний символ escape-последовательности
Пример с командной строкой OP: (OP = O первоначально)
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]
соответственно.
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 Color
G Horizontal cursor move
K Horizontal deletion
H New cursor position
F Move cursor to previous n lines
С помощью perl
Версия sed
Количество установленных в некоторых операционных системах может быть ограничено (например, MacOS X). Команда perl
имеет преимущество, заключающееся в том, что его часто проще устанавливать / обновлять в большем количестве операционных систем.
Выберите свое регулярное выражение в зависимости от того, сколько команд вы хотите отфильтровать:
perl -pe 's/\x1b\[[0-9;]*m//g' # Remove colors only
perl -pe 's/\x1b\[[0-9;]*[mG]//g'
perl -pe 's/\x1b\[[0-9;]*[mGKH]//g'
perl -pe 's/\x1b\[[0-9;]*[a-zA-Z]//g'
Пример с командной строкой OP:
perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset"' \
| perl -pe 's/\x1b\[[0-9;]*m//g'
использование
Как отмечается в комментарии Stuart Cardall, этот трюк используется проектом Ultimate Nginx Bad Bot (почти 1000 звезд) для очистки отчета по электронной почте;-)
Я нашел лучший способ удаления последовательности побега. Проверь это:
perl -pe 's/\x1b\[[0-9;]*[mG]//g'
ansi2txt
https://unix.stackexchange.com/a/527259/116915
cat typescript | ansi2txt | col -b
ansi2txt
: удалить цветовые коды ANSIcol -b
: удалять^H
или же^M
Если вы предпочитаете что-то простое, вы можете использовать модуль strip-ansi (требуется Node.js):
$ npm install --global strip-ansi-cli
Тогда используйте это так:
$ strip-ansi < colors.o
Или просто передайте строку:
$ strip-ansi '^[[37mABC^[[0m'
Что отображается как ^[
не ^
а также [
; это ASCII ESC
символ, созданный с помощью Esc или Ctrl[ (^
обозначение означает клавишу Ctrl).
ESC
0x1B шестнадцатеричный или 033 восьмеричный, поэтому вы должны использовать \x1B
или же \033
в ваших регулярных выражениях:
perl -pe 's/\033\[37m//g; s/\033[0m//g'
perl -pe 's/\033\[\d*(;\d*)*m//g'
Я считаю, что это авторитетное удаление всех 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, как и многие другие языки (но не sed), принимает \e
в качестве escape-персонажа Esc, \x1b
или же \033
по коду, показанному в терминалах как ^[
, Я использую это здесь, потому что это кажется более интуитивным.)
Эта команда perl, которую вы можете запустить все в одну строку, если хотите, содержит две замены. Первый идет после последовательностей CSI (последовательности escape-кодов, начинающиеся с "Представителя управляющих последовательностей" из Esc[, который охватывает гораздо больше, чем последовательности Select Graphic Rendition, которые составляют цветовые коды и другие текстовые декорации).
Вторая замена удаляет оставшиеся последовательности, которые включают в себя завершающие символы и оканчиваются на ST (терминатор строки, Esc\). Третья замена - это то же самое, но также позволяет завершать последовательности команд операционной системы с помощью BEL (\x07
, довольно часто \a
).
Четвертая замена удаляет оставшиеся побеги.
Также рассмотрите возможность удаления других символов ASCII нулевой ширины, таких как BEL и других более неясных управляющих символов C0 и C1. Я использую [\x00-\x1f\x7f-\x9f\xad]
, который также включает Delete и Soft Hyphen. Это исключает более длинные закодированные символы Unicode с нулевой шириной, но я считаю, что это исчерпывающее значение для ASCII (Unicode \x00
-\xff
). Если вы сделаете это, удалите эти последние, поскольку они могут быть включены в более длинные последовательности.
commandlinefu дает этот ответ, который отбрасывает цвета ANSI, а также команды перемещения:
sed "s,\x1B\[[0-9;]*[a-zA-Z],,g"
Для только цветов, вы хотите:
sed "s,\x1B\[[0-9;]*m,,g"
Также есть специальный инструмент для этой работы: ansifilter. Использовать по умолчанию
--text
Формат вывода.
Объединив ответы @Adam-Katz @Mike, я получаю:
sed -E $'s|\x1b\\[[0-\\?]*[ -/]*[@-~]||g;
s|\x1b[PX^_][^\x1b]*\x1b\\\\||g;
s:\x1b\\][^\x07]*(\x07|\x1b\\\\)::g;
s|\x1b[@-_]||g'
Это должно работать на macos, linux и mingw64x (Git для Windows)
Примечание. В очень старой версии GNU sed (до 4.2)
-E
флаг необходимо заменить на
-r
(как старый CentOS 6.0)
Объяснение регулярных выражений
1-й: Код ANSI CSI состоит из (по порядку)
- Один
\x1b
- Один
[
- Ноль или более байтов параметра
0x30-0x3f
- Ноль или более промежуточных байтов
0x20-0x2f
- Один последний байт
0x40-0x7f
2-й и 3-й: я не знаком с практикой, но читал о них на связанной странице.
4-й: просто поймать все, чтобы получить все оставшиеся escape-коды, при условии, что дополнительных байтов нет. Поскольку эти коды могут делать все, что захотят, возможно, байты данных останутся позади, но это крайне маловероятно, поскольку на практике они мало используются.
"tput sgr0" оставил этот управляющий символ ^(B^[
Вот модифицированная версия, чтобы позаботиться об этом.
perl -pe 's/\e[\[\(][0-9;]*[mGKFB]//g' logfile.log
"Ответ" на вопрос не сработал для меня, поэтому я вместо этого создал это регулярное выражение для удаления escape-последовательностей, создаваемых модулем perl Term::ANSIColor.
cat colors.o | perl -pe 's/\x1b\[[^m]+m//g;
Регулярное выражение Grawity должно работать нормально, но использование + тоже работает нормально.
Python-порт превосходного и исчерпывающего Adam Katz на Perl : ответа
def escape_ansi(line):
re1 = re.compile(r'\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]')
re2 = re.compile(r'\x1b[PX^_].*?\x1b\\')
re3 = re.compile(r'\x1b\][^\a]*(?:\a|\x1b\\)')
re4 = re.compile(r'\x1b[\[\]A-Z\\^_@]')
# re5: zero-width ASCII characters
# see https://superuser.com/a/1388860
re5 = re.compile(r'[\x00-\x1f\x7f-\x9f\xad]+')
for r in [re1, re2, re3, re4, re5]:
line = r.sub('', line)
return line
Сюда входит удаление последовательности C0/C1, поэтому удалите ее, если она вам не нужна. Я понимаю, что это не оптимизировано, поскольку используется несколько проходов регулярных выражений, но мне это помогло, и оптимизация меня не беспокоила.
Также рассмотрите возможность использованияcolorstrip
функция из этого модуля.
Colorstrip(STRING[, STRING ...]) Colorstrip() удаляет все escape-последовательности цвета из предоставленных строк, возвращая измененные строки отдельно в контексте массива или объединяя их вместе в скалярном контексте. Его аргументы не изменяются.
Мне приходилось искать это слишком много раз, поэтому я решил создать для этого бесплатный онлайн-инструмент. Для этого не нужно запоминать команды sed!
Надеюсь, вам это тоже подойдет: https://maxschmitt.me/ansistrip/
Это то, что у меня сработало (проверено на Mac OS X)
perl -pe 's/\[[0-9;]*[mGKF]//g'
У меня была похожая проблема с удалением символов, добавленных из сбора интерактивного верхнего вывода через замазку, и это помогло:
cat putty1.log | perl -pe 's/\x1b.*?[mGKH]//g'
Я знаю, что было много ответов о том, как поступить в ситуации, когда у вас есть файлы с этими символами. Ответ @oHo мне очень помог в этом.
Проблема:
cat sometext.txt > ansi_codes_in_file.txt
В случае, если у кого-то еще есть такая же основная причина проблемы, когда вывод осуществляется правильно вSTDOUT
(с цветами), но он записывает цветовые коды ANSI в файл, и вы хотите полностью этого избежать, вот что сработало для меня:
мне пришлось пересмотреть свой.bashrc
и файлы и обнаружил, что у меня есть следующая строка:
export GREP_OPTIONS='--color=always'
Увидев этот ответ: разные результаты в результатах grep при использовании опции --color=always
Никогда не используйте --color=always, если вы не знаете, что выходные данные должны содержать escape-последовательности ANSI - обычно для человеческих глаз на терминале.
Если вы не уверены, как обрабатываются входные данные, используйте --color=auto, который, как я полагаю, заставляет grep применять окраску только в том случае, если ее стандартный вывод подключен к терминалу.
Было ясно, что мне нужно изменить это в моем:
export GREP_OPTIONS='--color=auto'
После обновления моего.bash_profile
и загружаю конфигурацию в свой терминал (source ~/.bash_profile
) выполнение следующих работ без кодов ANSI в выходном файле
cat sometext.txt > no_ansi_codes_in_file.txt
Примечание:
- В моем случае у меня их не было
alias
установить на мойcat
команда
Это простое решение awk сработало для меня, попробуйте следующее:
str="happy $(tput setaf 1)new$(tput sgr0) year!"; #colored text
echo $str | awk '{gsub("(.\\[[0-9]+m|.\\(..\\[m)","",$0)}1'; #remove ansi colors