web-dev-qa-db-ja.com

bash:stderrを赤い色で印刷する

Bashを表示する方法はありますか stderr 赤い色のメッセージ?

124
kolypto
command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)
103
Balázs Pozsár

方法1:プロセス置換を使用します。

_command 2> >(sed $'s,.*,\e[31m&\e[m,'>&2)
_

方法2:bashスクリプトで関数を作成します。

_color()(set -o pipefail;"$@" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1
_

次のように使用します。

_$ color command
_

どちらの方法でも、コマンドのstderrが赤で表示されます。

方法2がどのように機能するかについての説明を読んでください。このコマンドによって示されるいくつかの興味深い機能があります。

  • color()... — colorというbash関数を作成します。
  • _set -o pipefail_ —これは、出力が別のコマンドにパイプされるコマンドのエラー戻りコードを保持するシェルオプションです。これは、外側のシェルのpipefailオプションを変更しないように、括弧によって作成されたサブシェルで行われます。
  • _"$@"_ —関数の引数を新しいコマンドとして実行します。 _"$@"_は_"$1" "$2" ..._と同等
  • _2>&1_ —コマンドのstderrstdoutにリダイレクトし、sedstdinにします。
  • _>&3_ — _1>&3_の短縮形です。これにより、stdoutが新しい一時ファイル記述子_3_にリダイレクトされます。 _3_は後でstdoutにルーティングされます。
  • _sed ..._ —上記のリダイレクトのため、sedstdinは実行されたコマンドのstderrです。その機能は、カラーコードで各行を囲むことです。
  • _$'...'_バックスラッシュでエスケープされた文字を理解させるbash構文
  • _.*_ —行全体と一致します。
  • _\e[31m_ —次の文字を赤にするANSIエスケープシーケンス
  • _&_ —一致した文字列全体(この場合は行全体)に展開されるsed置換文字。
  • _\e[m_ —色をリセットするANSIエスケープシーケンス。
  • _>&2_ — _1>&2_の短縮形です。これにより、sedstdoutstderrにリダイレクトされます。
  • _3>&1_ —一時ファイル記述子_3_をstdoutにリダイレクトします。
93
killdash9

Stderredをチェックアウトすることもできます: https://github.com/sickill/stderred

29
sickill

stderrを永続的に赤にするbashの方法は、「exec」を使用してストリームをリダイレクトすることです。以下をbashrcに追加してください:

exec 9>&2
exec 8> >(
    while IFS='' read -r line || [ -n "$line" ]; do
       echo -e "\033[31m${line}\033[0m"
    done
)
function undirect(){ exec 2>&9; }
function redirect(){ exec 2>&8; }
trap "redirect;" DEBUG
Prompt_COMMAND='undirect;'

私は以前これに投稿しました: STDOUTおよびSTDERRのフォント色を設定する方法

17
gospes
14
quaie

私は純粋なbashでBalázsPozsárの回答を実装するラッパースクリプトを作成しました。 $ PATHおよびprefixコマンドに保存して、出力を色分けします。

 
#!/ bin/bash 
 
 if [$ 1 == "--help"]; then 
 echo "コマンドを実行し、発生したすべてのエラーを色分けします" 
 echo "例:` basename $ {0} `wget ..." 
 echo "(c)o_O Tync 、ICQ#1227-700、エンジョイ! "
 exit 0 
 fi 
 
#すべてのエラーをキャッチする一時ファイル
 TMP_ERRS = $(mktemp )
 
#コマンドを実行します
 "$ @" 2>>(while read line; do echo -e "\ e [01; 31m $ line\e [0m" | tee --append $ TMP_ERRS; done)
 EXIT_CODE = $?
 
#すべてのエラーを再度表示します
 if [-s "$ TMP_ERRS"]; then 
 echo -e "\ n\n\n\e [01; 31m === ERRORS ===\e [0m" 
 cat $ TMP_ERRS 
 fi 
 rm -f $ TMP_ERRS 
 
#終了
 exit $ EXIT_CODE 
 
7
kolypto

このような関数を使用できます


 #!/bin/sh

color() {
      printf '\033[%sm%s\033[m\n' "$@"
      # usage color "31;5" "string"
      # 0 default
      # 5 blink, 1 strong, 4 underlined
      # fg: 31 red,  32 green, 33 yellow, 34 blue, 35 purple, 36 cyan, 37 white
      # bg: 40 black, 41 red, 44 blue, 45 purple
      }
string="Hello world!"
color '31;1' "$string" >&2
</ code>

>&2をstderrに出力するために追加します

3
Ali Mezgani

このソリューションは私にとってうまくいきました: https://superuser.com/questions/28869/immediately-tell-which-output-was-sent-to-stderr

この関数を.bashrcまたは.zshrc

# Red STDERR
# rse <command string>
function rse()
{
    # We need to wrap each phrase of the command in quotes to preserve arguments that contain whitespace
    # Execute the command, swap STDOUT and STDERR, colour STDOUT, swap back
    ((eval $(for phrase in "$@"; do echo -n "'$phrase' "; done)) 3>&1 1>&2 2>&3 | sed -e "s/^\(.*\)$/$(echo -en \\033)[31;1m\1$(echo -en \\033)[0m/") 3>&1 1>&2 2>&3
}

次に例:

$ rse cat non_existing_file.txt

赤の出力が得られます。

1
Eyal Levin

xargsとprintfを使用:

command 2> >(xargs -0 printf "\e[31m%s\e[m" >&2)
1

O_o Tyncのスクリプトを少し変更したバージョンがあります。 OS X Lion用にこれらのmodを作成する必要がありましたが、ラップされたコマンドが完了する前にスクリプトが完了する場合があるため、完璧ではありません。睡眠を追加しましたが、もっと良い方法があると確信しています。

#!/bin/bash

   if [ $1 == "--help" ] ; then
       echo "Executes a command and colorizes all errors occured"
       echo "Example: `basename ${0}` wget ..."
       echo "(c) o_O Tync, ICQ# 1227-700, Enjoy!"
       exit 0
       fi

   # Temp file to catch all errors
   TMP_ERRS=`mktemp /tmp/temperr.XXXXXX` || exit 1

   # Execute command
   "$@" 2> >(while read line; do echo -e "$(tput setaf 1)$line\n" | tee -a $TMP_ERRS; done)
   EXIT_CODE=$?

   sleep 1
   # Display all errors again
   if [ -s "$TMP_ERRS" ] ; then
       echo -e "\n\n\n$(tput setaf 1) === ERRORS === "
       cat $TMP_ERRS
   else
       echo "No errors collected in $TMP_ERRS"
   fi
   rm -f $TMP_ERRS

   # Finish
   exit $EXIT_CODE
1
Cliff

fifos を使用するバージョン

mkfifo errs
stdbuf -o0 -e0 -i0 grep . foo | while read line; do echo -e "\e[01;31m$line  \e[0m" >&2; done &
stdbuf -o0 -e0 -i0 sh $script 2>errs
0
untore