色付きの出力を生成するスクリプトがあり、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
も削除するにはどうすればよいですか?
スクリプト全体の色付けを完全に無効にする方法はありますか?
ウィキペディアによる 、使用しているsed
コマンドの[m|K]
は、m
(カラーコマンド)およびK
を処理するように特別に設計されています(「行の一部を消去」コマンド)。スクリプトは、カーソルの絶対位置を60(^[[60G
)に設定して、sed
行ではカバーされない行のすべてのOKを取得しようとしています。
(適切に、[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は確かにエコーで動作するため、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文字(シフトイン)(0x0f)も除去する方法を次に示します
./somescript | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sed "s/\x0f//g"
うーん、これがうまくいくかどうかはわかりませんが、 'tr'は 'strip'(削除)制御コード-試してください:
./somescript | tr -d '[:cntrl:]'
私見、これらの答えのほとんどは、エスケープコード内にあるものを制限するために一生懸命に努力します。その結果、[38;5;60m
(256色モードの前景ANSIカラー60)のような一般的なコードが欠落します。
また、 GNU拡張 を有効にする-r
オプションも必要です。これらは必須ではありません。正規表現を読みやすくするだけです。
256色のエスケープを処理し、GNU sed
以外のシステムで動作する簡単な回答を次に示します。
./somescript | sed 's/\x1B\[[0-9;]\+[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
を望ましくない文字の16進数に置き換えることで機能します)
同様の問題がありました。私が見つけた解決策はすべて、カラーコードに対してはうまく機能しましたが、"$(tput sgr0)"
(属性のリセット)によって追加された文字は削除しませんでした。
たとえば、 davemyronによるコメント の解を取得すると、次の例の結果の文字列の長さは6ではなく9です。
#!/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}" )"
テキストストリームから一般的なANSIコードを除外する純粋なBashの非常に単純な関数:
# 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
}
見る:
@ 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)
これを行う必要がある場合within 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