我有一些脚本可以生成带颜色的输出,我需要删除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
?
也许有办法完全禁用整个脚本的着色?
答案 0 :(得分:118)
According to Wikipedia,您使用的[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"
答案 1 :(得分:20)
我无法从其他任何答案中获得不错的结果,但以下内容对我有用:
somescript | sed -r "s/[[:cntrl:]]\[[0-9]{1,3}m//g"
如果我只删除了控制字符“^ [”,则它会留下其余的颜色数据,例如“33m”。包括颜色代码和“m”就可以了。我对s / \ x1B感到困惑// g不起作用,因为\ x1B [31m肯定适用于echo。
答案 2 :(得分:11)
嗯,不确定这是否适合你,但'tr'将'剥离'(删除)控制代码 - 尝试:
./somescript | tr -d '[:cntrl:]'
答案 3 :(得分:10)
对于Mac OSX或BSD使用
./somescript | sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g'
答案 4 :(得分:9)
恕我直言,大多数这些答案都试图限制转义代码中的内容。结果,它们最终会丢失常见的代码,例如[38;5;60m
(256色模式下的前景ANSI颜色60)。
他们还需要启用GNU extensions的-r
选项。这些不是必需的。他们只是使正则表达式的阅读效果更好。
这是处理256色转义符并在非GNU sed
的系统上工作的简单答案:
./somescript | sed 's/\x1B\[[0-9;]\+[A-Za-z]//g'
这将捕获以[
开头,具有任意数量的小数和分号以及以字母结尾的所有内容。这应该捕获任何common ANSI escape sequences。
对于趣味性,这是针对all conceivable ANSI escape sequences的更大,更通用(但未经测试)的解决方案:
./somescript | sed 's/\x1B[@A–Z\\\]^_]|\x1B\[[0–9:;<=>?]*[-!"#$%&\'()*+,.\/]*[@A–Z[\\\]^_`a–z{|}~]//g'
(如果您有@ edi9999的SI问题,请在末尾添加| sed "s/\x0f//g"
;将0f
替换为不需要的char的十六进制,对于any control char来说是有效的)
答案 5 :(得分:8)
我也遇到了问题,有时候会出现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 :(得分:4)
我有类似的问题。我发现所有解决方案都适用于颜色代码,但没有删除"$(tput sgr0)"
添加的字符(重置属性)。
例如,在下面的示例中,comment by 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}" )"
答案 7 :(得分:3)
@ 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 :(得分:3)
纯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
}
请参阅:
答案 9 :(得分:3)
有争议的想法是为此过程环境重新配置终端设置,以使过程知道终端不支持颜色。
我想到TERM=xterm-mono ./somescript
之类的东西。具有特定操作系统的YMMV以及脚本了解终端颜色设置的功能。
答案 10 :(得分:3)
我在 Debian 的 ansi2txt
软件包中遇到了 colorized-logs
工具。该工具从 STDIN 中删除 ANSI 控制代码。
用法示例:
./somescript | ansi2txt
答案 11 :(得分:1)
如果需要在>强大的>> Bash脚本中执行此操作,可以使用以下函数:
# 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
}
这是一个匹配原始问题用例的示例。保存为example.sh
,然后运行<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
答案 12 :(得分:1)
还有一个专用工具来处理ANSI转义序列:ansifilter。使用默认的--text
输出格式删除所有ANSI转义序列(注意:不仅是着色)。
答案 13 :(得分:0)
我遇到了这个问题/答案,试图做与OP类似的事情。我找到了其他有用的资源,并根据这些资源提出了一个日志脚本。张贴在这里,以防其他人得到帮助。
深入研究链接有助于了解一些重定向信息,这些信息我不会尝试解释,因为我自己才刚刚开始理解它。
用法将彩色输出呈现到控制台,同时从转到日志文件的文本中剥离颜色代码。对于任何不起作用的命令,它还将在日志文件中包含stderr。
编辑:在底部添加更多用法以显示如何以不同方式登录
#!/bin/bash
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
. $DIR/dev.conf
. $DIR/colors.cfg
filename=$(basename ${BASH_SOURCE[0]})
# remove extension
# filename=`echo $filename | grep -oP '.*?(?=\.)'`
filename=`echo $filename | awk -F\. '{print $1}'`
log=$DIR/logs/$filename-$target
if [ -f $log ]; then
cp $log "$log.bak"
fi
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>$log 2>&1
# log message
log(){
local m="$@"
echo -e "*** ${m} ***" >&3
echo "=================================================================================" >&3
local r="$@"
echo "================================================================================="
echo -e "*** $r ***" | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g"
echo "================================================================================="
}
echo "=================================================================================" >&3
log "${Cyan}The ${Yellow}${COMPOSE_PROJECT_NAME} ${filename} ${Cyan}script has been executed${NC}"
log $(ls) #log $(<command>)
log "${Green}Apply tag to image $source with version $version${NC}"
# log $(exec docker tag $source $target 3>&2) #prints error only to console
# log $(docker tag $source $target 2>&1) #prints error to both but doesn't exit on fail
log $(docker tag $source $target 2>&1) && exit $? #prints error to both AND exits on fail
# docker tag $source $target 2>&1 | tee $log # prints gibberish to log
echo $? # prints 0 because log function was successful
log "${Purple}Push $target to acr${NC}"
以下其他链接也有帮助:
答案 14 :(得分:0)
不确定./somescript
中的内容,但是如果未对转义序列进行硬编码,则可以设置终端类型来避免它们
TERM=dumb ./somescript
例如,如果您尝试
TERM=dumb tput sgr0 | xxd
您会看到它在一段时间内不产生任何输出
tput sgr0 | xxd
00000000: 1b28 421b 5b6d .(B.[m
(对于xterm-256color)。
答案 15 :(得分:0)
我使用了perl,因为我经常在许多文件上执行此操作。这将遍历所有文件名为* .txt的文件,并将删除所有格式。这适用于我的用例,对其他人也可能有用,因此只需在此处发布即可。替换文件名代替文件名* .txt的任何文件,或者可以在下面设置FILENAME变量时将文件名用空格分隔。
$ FILENAME = $(ls文件名* .txt);用于$(echo $ FILENAME)中的文件;回显$ file;猫$文件| perl -pe's / \ e([^ []] | [。?[a-zA-Z] |]。?\ a)// g'| col -b> $ file-new; mv $ file-new $ file;完成
答案 16 :(得分:-5)
这对我有用:
./somescript | cat