Удаление цветов с вывода
У меня есть сценарий, который производит вывод с цветами, и мне нужно удалить коды ANSI.
#!/bin/bash
exec > >(tee log) # redirect the output to a file but keep it on stdout
exec 2>&1
./somescript
Вывод (в файле журнала):
java (pid 12321) is [email protected][60G[@[0;32m OK @[0;39m]
Я не знал, как поместить символ ESC здесь, поэтому я поставил @
на его место.
Я изменил сценарий на:
#!/bin/bash
exec > >(tee log) # redirect the output to a file but keep it on stdout
exec 2>&1
./somescript | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"
Но теперь это дает мне (в файле журнала):
java (pid 12321) is [email protected][60G[ OK ]
Как я могу также удалить это ' @[60G
?
Может быть, есть способ полностью отключить раскраску для всего сценария?
Ответы
Ответ 1
Согласно Википедии, [m|K]
в используемой вами команде sed
специально разработана для обработки m
(цветовой команды) и K
(команда "стереть часть строки"). Ваш скрипт пытается установить абсолютную позицию курсора в 60 (^[[60G
), чтобы получить все ОК в строке, которую ваша строка sed
не покрывает.
(Правильно, [m|K]
вероятно, должно быть (m|K)
или [mK]
, потому что вы не пытаетесь сопоставить символ канала. Но это сейчас не важно.)
Если вы переключите последнее совпадение в вашей команде на [mGK]
или (m|G|K)
, вы сможете перехватить эту дополнительную последовательность управления.
./somescript | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g"
Ответ 2
Я не мог получить достойные результаты от любых других ответов, но следующее работало для меня:
somescript | sed -r "s/[[:cntrl:]]\[[0-9]{1,3}m//g"
Если я удалил только элемент управления char "^ [", он оставил остальные данные цвета, например, "33 м". В том числе цветовой код и "м" сделали трюк. Я озадачен s/\ x1B//g не работает, потому что \x1B [31m, безусловно, работает с эхом.
Ответ 3
Хм, не уверен, что это сработает для вас, но 'tr' будет 'strip' (удалить) управляющие коды - попробуйте:
./somescript | tr -d '[:cntrl:]'
Ответ 4
ИМХО, большинство из этих ответов слишком стараются ограничить то, что находится внутри escape-кода. В результате они теряют общие коды, такие как [38;5;60m
(основной цвет ANSI 60 из 256-цветного режима).
Им также требуется опция -r
которая включает расширения GNU. Это не обязательно; они просто делают регулярное выражение лучше.
Вот более простой ответ, который обрабатывает 256-цветное экранирование и работает в системах с non-GNU sed
:
./somescript | sed 's/\x1B\[[0-9;]\+[A-Za-z]//g'
Это поймает все, что начинается с [
, имеет любое количество десятичных и точек с запятой и заканчивается буквой. Это должно поймать любую из общих escape-последовательностей ANSI.
Для забавы, здесь более широкое и более общее (но не проверенное) решение для всех мыслимых escape-последовательностей ANSI:
./somescript | sed 's/\x1B[@A–Z\\\]^_]|\x1B\[[0–9:;<=>?]*[-!"#$%&\'()*+,.\/]*[@A–Z[\\\]^_'a–z{|}~]//g'
(и если у вас есть проблема @edi9999 SI, добавьте | sed "s/\x0f//g"
в конец; это работает для любого контрольного символа, заменяя 0f
на шестнадцатеричный из нежелательного символа)
Ответ 5
У меня также была проблема, что иногда появляется символ SI.
Это произошло, например, с помощью этого ввода: echo "$(tput setaf 1)foo$(tput sgr0) bar"
Здесь также можно разбить символ SI (сдвиг в) (0x0f)
./somescript | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sed "s/\x0f//g"
Ответ 6
Для Mac OSX или BSD использовать
./somescript | sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g'
Ответ 7
@решение jeff-bowman помогло мне избавиться от НЕКОТОРЫХ цветовых кодов.
Я добавил еще одну небольшую часть в регулярное выражение, чтобы удалить еще несколько:
sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" # Original. Removed Red ([31;40m[1m[error][0m)
sed -r "s/\x1B\[([0-9];)?([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" # With an addition, removed yellow and green ([1;33;40m[1m[warning][0m and [1;32;40m[1m[ok][0m)
^^^^^^^^^
remove Yellow and Green (and maybe more colors)
Ответ 8
У меня была похожая проблема. Все решения, которые я нашел, работали хорошо для цветовых кодов, но не удаляли символы, добавленные "$(tput sgr0)"
(сброс атрибутов).
Взяв, к примеру, решение в комментарии davemyron, длина полученной строки в приведенном ниже примере равна 9, а не 6:
#!/usr/bin/env bash
string="$(tput setaf 9)foobar$(tput sgr0)"
string_sed="$( sed -r "s/\x1B\[[0-9;]*[JKmsu]//g" <<< "${string}" )"
echo ${#string_sed}
Для правильной работы регулярное выражение должно быть расширено, чтобы соответствовать последовательности, добавленной sgr0
(" \E(B
"):
string_sed="$( sed -r "s/\x1B(\[[0-9;]*[JKmsu]|\(B)//g" <<< "${string}" )"
Ответ 9
Гораздо более простая функция в чистом Bash для фильтрации общих кодов ANSI из текстового потока:
# Strips common ANSI codes from a text stream
shopt -s extglob # Enable Bash Extended Globbing expressions
ansi_filter() {
local line
local IFS=
while read -r line || [[ "$line" ]]; do
echo "${line//$'\e'[\[(]*([0-9;])[@-n]/}"
done
}
Увидеть:
- linuxjournal.com: расширенная глобализация
- gnu.org: расширение параметров Bash
Ответ 10
Если вам нужно выполнить этот внутри сценарий Bash, можно использовать следующую функцию:
# Коды/последовательности удаления полосы пропускания [$ 1: ввод, $2: целевая переменная]
function strip_escape_codes() { local input = "$ {1//\" /\\\ "}" output = "я char внутри_код = 0 for ((i = 0; я < ${# input}; ++ i)); делать char =" ${input: i: 1} "# получить текущий символ if (($ {in_code} == 1)); тогда #, если мы в настоящее время находимся в коде эвакуации, проверьте, case" ${char} "в # коде, то есть, если текущий символ является буквой [a-zA-Z]) внутри_код = 0;; # мы больше не находимся в escape-коде ESAC Продолжать фи if [[" ${char} "== $'\ e']]; то #, если текущий символ равен '\ e', мы достигли кода выхода in_code = 1 # теперь мы находимся в escape-коде Продолжать фи output + =" ${char} "#, если ничего из вышеприведенного не применяется, добавьте текущий символ для вывода сделанный eval" $2 = \ "${output}\" " # назначить вывод целевой переменной
}
Код>
Вот пример, соответствующий варианту использования исходного вопроса. Сохраните как example.sh
, а затем запустите < command-production-color-output > | example.shкод>:
<Предварительно > <код > #!/Bin/Баш
# copy & вставить функцию strip_escape_codes здесь
при чтении строки -r; делать strip_escape_codes "$ {line}" лишен echo "$ {stripped}"
сделанный
Код >
Ответ 11
Это работает для меня:
./somescript | cat