我有一些脚本,产生输出的颜色,我需要删除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?

也许有一种方法可以完全禁用整个脚本的着色?


当前回答

还有一个专门处理ANSI转义序列的工具:ansifilter。使用默认的——text输出格式去除所有的ANSI转义序列(注意:不仅仅是着色)。

裁判:https://stackoverflow.com/a/6534712

其他回答

恕我直言,大多数答案都过于努力地限制转义代码中的内容。结果,它们最终会丢失常见的代码,如[38;5;60m(前景色ANSI颜色60来自256色模式)。

它们还需要启用GNU扩展的-r选项。这些都不是必需的;它们只是让正则表达式读起来更好。

下面是一个更简单的答案,它处理256色转义,并在非gnu sed系统上工作:

./somescript | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g'

这将捕获以[开头,有任意数量的小数和分号,并以字母结尾的任何内容。这应该捕获任何常见的ANSI转义序列。

对于所有可能的ANSI转义序列,这里有一个更大、更通用(但最少测试)的解决方案:

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

(如果你有@edi9999的SI问题,在后面加上| sed "s/\x0f//g";这适用于任何控制字符,用不需要的字符的十六进制替换0f)

在纯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
    printf '%s\n' "${line//$'\e'[\[(]*([0-9;])[@-n]/}"
  done
}

See:

扩展Globbing gnu.org: Bash参数扩展

我的贡献:

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

还有一个专门处理ANSI转义序列的工具:ansifilter。使用默认的——text输出格式去除所有的ANSI转义序列(注意:不仅仅是着色)。

裁判:https://stackoverflow.com/a/6534712

这对我来说很管用:

./somescript | cat