developer tip

출력에서 색상 제거

optionbox 2020. 7. 25. 10:50
반응형

출력에서 색상 제거


색상으로 출력을 생성하는 스크립트가 있으며 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 running...@[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 running...@[60G[  OK  ]

이걸 어떻게 제거 할 수 @[60G있습니까?

전체 스크립트의 색상을 완전히 비활성화하는 방법이 있습니까?


위키 백과에 따르면[m|K]에서 sed사용중인 명령은 특별히 처리 할 수 있도록 설계되어있다 m(색상 명령)과 K(이하 "라인의 삭제 부분"명령). 스크립트가 절대 커서 위치를 60 ( ^[[60G) 으로 설정 하여 한 줄의 모든 OK를 얻지 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"

다른 답변에서 괜찮은 결과를 얻을 수 없었지만 다음이 저에게 효과적이었습니다.

somescript | sed -r "s/[[:cntrl:]]\[[0-9]{1,3}m//g"

제어 문자 "^ ["만 제거하면 나머지 색상 데이터 (예 : "33m")가 남았습니다. 색상 코드와 "m"을 포함하여 트릭을 수행했습니다. \ x1B [31m이 확실히 echo와 함께 작동하기 때문에 s / \ x1B // g가 작동하지 않습니다.


Mac OSX 또는 BSD 사용

./somescript | sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g'

또한 때때로 SI 캐릭터가 등장한다는 문제가있었습니다.

예를 들어이 입력으로 발생했습니다. echo "$(tput setaf 1)foo$(tput sgr0) bar"

다음은 SI 문자를 제거하는 방법입니다 (shift in) (0x0f).

./somescript | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sed "s/\x0f//g"

IMHO, 이러한 답변의 대부분은 이스케이프 코드 내부의 내용을 제한하기 위해 너무 열심히 노력합니다. 결과적으로 [38;5;60m(256 색상 모드의 전경 ANSI 색상 60) 과 같은 공통 코드가 누락 됩니다.

또한 GNU 확장-r 을 가능하게 하는 옵션이 필요합니다 . 이것들은 필요하지 않습니다. 그들은 정규식을 더 잘 읽습니다.

다음은 256 색 이스케이프를 처리하고 GNU가 아닌 시스템에서 작동하는 간단한 답변입니다 sed.

./somescript | sed 's/\x1B\[[0-9;]\+[A-Za-z]//g'

이것은로 시작하고 [, 소수와 세미콜론을 포함하며, 문자로 끝나는 모든 것을 잡을 것입니다 . 이것은 일반적인 ANSI 이스케이프 시퀀스 중 하나를 잡아야합니다 .

For funsies, here's a larger and more general (but untested) solution for all conceivable ANSI escape sequences:

./somescript | sed 's/\x1B[@A–Z\\\]^_]|\x1B\[[0–9:;<=>?]*[-!"#$%&\'()*+,.\/]*[@A–Z[\\\]^_`a–z{|}~]//g'

(and if you have @edi9999's SI problem, add | sed "s/\x0f//g" to the end; this works for any control char by replacing 0f with the hex of the undesired char)


Hmm, not sure if this will work for you, but 'tr' will 'strip' (delete) control codes - try:

./somescript | tr -d '[:cntrl:]'

I had a similar problem. All solutions I found did work well for the color codes but did not remove the characters added by "$(tput sgr0)" (resetting attributes).

Taking, for example, the solution in the comment by davemyron the length of the resulting string in the example below is 9, not 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}

In order to work properly, the regex had to be extend to also match the sequence added by sgr0 ("\E(B"):

string_sed="$( sed -r "s/\x1B(\[[0-9;]*[JKmsu]|\(B)//g" <<< "${string}" )"

@jeff-bowman's solution helped me getting rid of SOME of the color codes. I added another small portion to the regex in order to remove some more:

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)

Much simpler function in pure Bash to filter-out common ANSI codes from a text stream:

# 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
}

See:

  1. linuxjournal.com: Extended Globbing
  2. gnu.org: Bash Parameter Expansion

If one needs to do this within a Bash script, the following function may be used:

# Strip escape codes/sequences [$1: input, $2: target variable]
function strip_escape_codes() {
    local input="${1//\"/\\\"}" output="" i char within_code=0
    for ((i=0; i < ${#input}; ++i)); do
        char="${input:i:1}"                     # get current character
        if (( ${within_code} == 1 )); then      # if we're currently within an escape code, check if end of
            case "${char}" in                   # code is reached, i.e. if current character is a letter
                [a-zA-Z]) within_code=0 ;;      # we're no longer within an escape code
            esac
            continue
        fi
        if [[ "${char}" == $'\e' ]]; then       # if current character is '\e', we've reached an escape code
            within_code=1                       # now we're within an escape code
            continue
        fi
        output+="${char}"                       # if none of the above applies, add current character to output
    done
    eval "$2=\"${output}\""                     # assign output to target variable
}

Here's an example matching the use case of the original question. Save as example.sh and then run <command-producing-colored-output> | example.sh:

#!/bin/bash

# copy&paste function strip_escape_codes here

while read -r line; do
    strip_escape_codes "${line}" stripped
    echo "${stripped}"
done

This works for me:

./somescript | cat

참고URL : https://stackoverflow.com/questions/17998978/removing-colors-from-output

반응형