आउटपुट से रंग निकालना


140

मेरे पास कुछ स्क्रिप्ट हैं जो रंगों के साथ आउटपुट पैदा करती हैं और मुझे एएनएसआई कोड हटाने की जरूरत है।

#!/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]

मुझे नहीं पता कि ईएससी चरित्र को यहां कैसे रखा जाए, इसलिए मैंने @इसकी जगह पर रखा ।

मैंने स्क्रिप्ट को इसमें बदल दिया:

#!/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?

शायद पूरी स्क्रिप्ट के लिए रंग को पूरी तरह से अक्षम करने का एक तरीका है?


नोड / एनपीएम के लिए, आप उपयोग कर सकते हैं strip-ansi: github.com/chalk/strip-ansi
यहोशू पिंटर

जवाबों:


165

विकिपीडिया के अनुसार , [m|K]में sedआदेश का उपयोग कर रहे विशेष रूप से संभाल करने के लिए डिज़ाइन किया गया है m(रंग आदेश) और K( "लाइन के मिटा हिस्सा" कमांड)। आपकी स्क्रिप्ट ^[[60Gएक लाइन में सभी ओके पाने के लिए 60 ( ) पर पूर्ण कर्सर स्थिति सेट करने की कोशिश कर रही है , जिसे आपकी sedलाइन कवर नहीं करती है।

(उचित रूप से, [m|K]संभवतः होना चाहिए (m|K)या [mK], क्योंकि आप एक पाइप चरित्र से मेल खाने की कोशिश नहीं कर रहे हैं। लेकिन अभी यह महत्वपूर्ण नहीं है।)

यदि आप उस अंतिम मैच को अपने कमांड में [mGK]या (m|G|K), पर स्विच करते हैं , तो आपको उस अतिरिक्त नियंत्रण अनुक्रम को पकड़ने में सक्षम होना चाहिए।

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

29
BSD / OSX उपयोगकर्ता: हमारे पास आमतौर पर sed के लिए -r विकल्प नहीं है। brew install gnu-sedएक सक्षम संस्करण स्थापित करेगा। साथ चलाना gsed
निकोलई एस

1
यदि मैं करता हूं echo "$(tput setaf 1)foo$(tput sgr0) bar" | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | cat -A, मुझे मिलता है: foo^O bar$तो मुझे लगता है कि कुछ अक्षर सही ढंग से नहीं हटाए गए हैं, है ना? क्या आप जानते हैं कि कैसे सही करें?
edi9999

1
@ edi9999 जहां तक ​​मैं बता सकता हूं, वहां अंतर यह है कि 16 रंगों से परे रंग सेटिंग्स ( setafसमर्थन के रूप में ) सिर्फ दो से अधिक मापदंडों की आवश्यकता होती है; मेरा regex दो का समर्थन करता है। मदद के ?लिए पहले बाहर बदलना *चाहिए। हैंडलिंग sgr0संभव है लेकिन एक खोज के आधार पर यह संभव है कि यह हैक रेगेक्स-आधारित उत्तर के दायरे से बाहर हो।
जेफ बोमैन

ठीक है, मैंने एक उत्तर जोड़ा है जो sedपाइप में "शिफ्ट" चरित्र को
छीनने के लिए जोड़ देता है

7
यह मज़बूती से काम नहीं करता है क्योंकि तीसरा मान (ala [38;5;45m) हो सकता है। यह वैकल्पिक उत्तर unix.stackexchange.com/a/55547/168277
davemyron

30

मुझे अन्य किसी भी उत्तर से अच्छे परिणाम नहीं मिल सके, लेकिन निम्नलिखित में मेरे लिए काम किया गया:

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

अगर मैंने केवल नियंत्रण वर्ण "^ [" को हटा दिया, तो इसने शेष रंग डेटा को छोड़ दिया, उदाहरण के लिए, "33m"। रंग कोड और "एम" सहित चाल किया। मैं s / \ X1B // g से काम नहीं कर रहा / रही हूँ क्योंकि \ X1B [31m निश्चित रूप से प्रतिध्वनि के साथ काम करता है।


6
OSX (BSD sed) पर, विस्तारित रेगेक्स के -Eबजाय उपयोग करें -r। यहाँ और अधिक पाया जा सकता है
अस्मांबर '’१।

मैं बदलने के लिए किया था {1,3}के लिए {,3}(अन्यथा यह अभी भी कुछ नियंत्रण लंघन गया था), अपने समाधान के लिए धन्यवाद!
एक्शनलेस

6
चूंकि वे अर्ध-कॉलनों (पृष्ठभूमि के रंग, बोल्ड, इटैलिक, आदि ...) के साथ अलग-अलग संख्या में हो सकते हैं। इस कमांड ने मेरे लिए काम किया:sed -r "s/[[:cntrl:]]\[([0-9]{1,3};)*[0-9]{1,3}m//g"
saeedgnu

यह एक (कई मैंने परीक्षण किया) अंसिबल आउटपुट के साथ काम किया था जो अनबफर के साथ चलाया गया था।
मार्टिन

23

IMHO, इनमें से अधिकांश उत्तर भागने के कोड के अंदर क्या है, इसे प्रतिबंधित करने के लिए बहुत अधिक प्रयास करते हैं। नतीजतन, वे लापता सामान्य कोड को समाप्त करते हैं, जैसे [38;5;60m(256 रंग मोड से अग्रभूमि एएनएसआई रंग 60)।

उन्हें -rविकल्प की भी आवश्यकता होती है जो GNU एक्सटेंशन को सक्षम बनाता है । इनकी आवश्यकता नहीं है; वे सिर्फ रेगेक्स को बेहतर ढंग से पढ़ते हैं।

यहां एक सरल उत्तर है जो 256-रंग से बचता है और गैर-जीएनयू के साथ सिस्टम पर काम करता है sed:

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

यह कुछ भी है कि के साथ शुरू होता है [, दशमलव और अर्धविराम की कोई भी संख्या है, और एक पत्र के साथ समाप्त होता है। यह किसी भी सामान्य एएनएसआई से बचने के क्रम को पकड़ना चाहिए ।

मौज-मस्ती के लिए, यहां एक बड़ा और अधिक सामान्य (लेकिन न्यूनतम परीक्षण किया गया) सभी कल्पनीय एएनएसआई से बचने के लिए समाधान है :

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

(और अगर आपको @ edi9999 की SI समस्या है, | sed "s/\x0f//g"तो अंत में जोड़ें ; यह अवांछित नियंत्रण0f के हेक्स के साथ प्रतिस्थापित करके किसी भी नियंत्रण चार के लिए काम करता है )


यह एक अच्छी तरह से Azure az cli prettified आउटपुट से स्ट्रिंग रंग के लिए काम करता है।
वोल्वोक्स

फिक्स्ड @elig। पता चलता है कि यह कई मुद्दों पर था, कुछ संपादकों ने अजीब यूनिकोड संस्करणों के साथ मेरे सभी डैश को बदलने के साथ शुरू किया, लेकिन अनुचित भागने का एक गुच्छा - |sed में, ]एक चरित्र वर्ग के अंदर sed में, और 'एक एकल-उद्धरण वाले स्ट्रिंग स्ट्रिंग में। यह अब मेरे लिए बहुत ही बुनियादी परीक्षण के मामले में काम कर रहा है।
म्रत

20

Mac OSX या BSD के उपयोग के लिए

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

1
अजीब बात है, यह एक डेबियन के लिए ठीक काम किया है लेकिन अन्य ऊपर नहीं किया।
साइबर

यह एक आंशिक रूप से काम किया। हालांकि, अगर मैं एक्सेल में एक फ़ाइल खोलता हूं, तो मैं अभी भी इस विशेष चरित्र को देख रहा हूं "?" प्रत्येक पंक्ति के अंत में।
doudy_05

@ doudy_05 -Eविस्तारित regexp को सक्षम करने के लिए sed के लिए ध्वज को पास करने का प्रयास करें ।
अलेक्जेंडर ज़िनचेंको

14

मुझे यह भी समस्या थी कि कभी-कभी, एसआई चरित्र दिखाई देता था।

यह इस इनपुट के साथ उदाहरण के लिए हुआ: 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"

2
यकीन नहीं होता कि इस जवाब को इतना कम क्रेडिट क्यों मिला। यह मेरे लिए एकमात्र काम है ...
15

8

हम्म, निश्चित नहीं कि यह आपके लिए काम करेगा, लेकिन 'tr' विल 'स्ट्रिप' (डिलीट) कंट्रोल कोड - कोशिश:

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

32
अचानक यह नई लाइनों को भी हटा रहा है
बर्बाद करें

हां, एलएफ और सीआर (कोड) नियंत्रण कोड हैं; यदि आपकी रुचि एक से अधिक लाइन में है तो यह समाधान नहीं हो सकता है। चूंकि यह प्रतीत होता है कि आप एक जावा कार्यक्रम चला रहे हैं, इसलिए मैं अनुमान लगाऊंगा कि रंगों का प्रबंधन वहां से किया जाता है; अन्यथा आपको अपना कंसोल सेटअप (यानी टर्मिनल सेटिंग्स / कलर स्कीम) और / या 'रंग' का समर्थन करने वाले प्रत्येक कमांड के विकल्पों पर, यानी ls
--color

3
मुझे इसके लालित्य के लिए यह उत्तर पसंद है, भले ही यह रंगों को हटाने से अधिक हो। धन्यवाद!
जोहान फिलिप स्ट्रैटहॉजेन

7
यह वास्तव में वहां कोड देता है, ls -l + your कमांड देखें:rwxr-xr-x 1 tokra admin 22 Oct 18 14:21 [0m[01;36m/usr/local/opt/gradle[0m -> [01;34m../Cellar/gradle/4.2.1[0m/
To Kra

7

मुझे भी ऐसी ही समस्या का समाधान करना पड़ा था। मैंने पाया सभी समाधान रंग कोडों के लिए अच्छी तरह से काम करते थे, लेकिन उनके द्वारा जोड़े गए वर्णों को नहीं हटाया गया "$(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}" )"

@Jarodiv - सबसे आकर्षक दृष्टिकोण के लिए धन्यवाद। इस विषय पर प्रदान किए गए सभी उत्तर केवल ANSI / VT100 नियंत्रण अनुक्रमों के साथ सौदा करते हैं (उदा: "\ e [31mHello World \ e [0m"), हालाँकि TPUT पाठ स्वरूपण (उदा। Tput smso / tput setaf X) के कारण होने वाली किसी भी चीज़ का पुनर्लेखन नहीं होता है। / tput rmso / tput sgr0)। परिणामस्वरूप सभी 'सेड' निष्पादित होने के बाद लॉग में कुछ और गड़बड़ बची थी। यह मेरे usecases के लिए एक शुद्ध समाधान है!
फेसलेस

5

एक पाठ स्ट्रीम से सामान्य 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: बैश पैरामीटर विस्तार

1
यह काम नहीं करता है। के साथ टेस्ट करें tldr। (हालांकि मैं zsh का उपयोग करता हूं इसलिए यह उसी के कारण भी हो सकता है।)
हैप्पीफेस

वास्तव में, Zash बाश के विस्तारित ग्लोब को नहीं समझेगा extglobया शायद न ही इसे स्ट्रिंग प्रतिस्थापन को पूरी तरह से समझेगा।
लेआ ग्रिस

मैंने zsh के विस्तारितग्लोबल को सक्षम किया ... स्ट्रिंग प्रतिस्थापन को पॉज़िक्स भी होना चाहिए?
HappyFace

स्ट्रिंग रिप्लेसमेंट POSIX नहीं है। आप sedयहां बताए गए किसी भी वैकल्पिक तरीके का उपयोग कर सकते हैं जो Zsh के साथ काम करेगा।
Léa Gris

इस समाधान में टेक्स्ट को लाइन-बफ़र करने का लाभ है। मैंने सेड के साथ कोशिश की लेकिन यह मेरे पाइप को ब्लॉक कर रहा था।
गिलर्मो प्रांडी

3

@ jeff-bowman के समाधान ने मुझे कुछ रंग कोडों से छुटकारा पाने में मदद की। कुछ और निकालने के लिए मैंने regex में एक और छोटा भाग जोड़ा:

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)

2

यहाँ एक शुद्ध बैश समाधान है।

के रूप में सहेजें strip-escape-codes.sh, निष्पादन योग्य बनाएं और फिर चलाएं <command-producing-colorful-output> | ./strip-escape-codes.sh

ध्यान दें कि यह सभी ANSI एस्केप कोड / क्रम को स्ट्रिप्स करता है । यदि आप केवल रंगों को पट्टी करना चाहते हैं, तो इसके [a-zA-Z]साथ बदलें "m"

बैश> = 4.0:

#!/usr/bin/env bash

# Strip ANSI escape codes/sequences [$1: input string, $2: target variable]
function strip_escape_codes() {
    local _input="$1" _i _char _escape=0
    local -n _output="$2"; _output=""
    for (( _i=0; _i < ${#_input}; _i++ )); do
        _char="${_input:_i:1}"
        if (( ${_escape} == 1 )); then
            if [[ "${_char}" == [a-zA-Z] ]]; then
                _escape=0
            fi
            continue
        fi
        if [[ "${_char}" == $'\e' ]]; then
            _escape=1
            continue
        fi
        _output+="${_char}"
    done
}

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

बैश <4.0:

#!/usr/bin/env bash

# Strip ANSI escape codes/sequences [$1: input string, $2: target variable]
function strip_escape_codes() {
    local input="${1//\"/\\\"}" output="" i char escape=0
    for (( i=0; i < ${#input}; ++i )); do         # process all characters of input string
        char="${input:i:1}"                       # get current character from input string
        if (( ${escape} == 1 )); then             # if we're currently within an escape sequence, check if
            if [[ "${char}" == [a-zA-Z] ]]; then  # end is reached, i.e. if current character is a letter
                escape=0                          # end reached, we're no longer within an escape sequence
            fi
            continue                              # skip current character, i.e. do not add to ouput
        fi
        if [[ "${char}" == $'\e' ]]; then         # if current character is '\e', we've reached the start
            escape=1                              # of an escape sequence -> set flag
            continue                              # skip current character, i.e. do not add to ouput
        fi
        output+="${char}"                         # add current character to output
    done
    eval "$2=\"${output}\""                       # assign output to target variable
}

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

खैर, यह समाधान और भी कम जटिल हो सकता है।
अलेक्जेंडर ज़िनचेंको

1

विवादास्पद विचार इस प्रक्रिया के वातावरण के लिए टर्मिनल सेटिंग्स को फिर से कॉन्फ़िगर करना होगा ताकि प्रक्रिया को यह पता चल सके कि टर्मिनल रंगों का समर्थन नहीं करता है।

TERM=xterm-mono ./somescriptमेरे दिमाग में कुछ ऐसा आता है। अपने विशिष्ट OS और टर्मिनल रंग सेटिंग्स को समझने के लिए आपकी स्क्रिप्ट की क्षमता के साथ YMMV।


-7

यह मेरे लिए काम करता है:

./somescript | cat

3
यह इस बात पर निर्भर करता है कि somescriptइसे कैसे लागू किया जाता है। यह पहचान सकता है कि इसका मानक आउटपुट ट्टी है या नहीं। (शब्द अपराधी वास्तव में कार्यक्रम में हार्ड-कोड टर्मिनल-विशिष्ट एस्केप कोड हैं, और जब अन्य टर्मिनलों या लिपियों में उपयोग किए जाते हैं तो बहुत बुरी तरह से टूट जाते हैं)।
टोबे स्पाइट

धन्यवाद टोबी। मैंने परीक्षण करने के लिए django's manage.py का उपयोग किया, लेकिन आपने जो कहा वह समझ में आता है।
स्पाइडरलामा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.