Удаление цветов с вывода

У меня есть сценарий, который производит вывод с цветами, и мне нужно удалить коды 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
}

Увидеть:

  1. linuxjournal.com: расширенная глобализация
  2. 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