web-dev-qa-db-ja.com

BashヒアドキュメントでANSIカラーエスケープコードを使用することは可能ですか?

メッセージをBashスクリプトで印刷していますが、メッセージの一部を色分けします。例えば、

#!/bin/bash

normal='\e[0m'
yellow='\e[33m'
cat <<- EOF
    ${yellow}Warning:${normal} This script repo is currently located in:
    [ more messages... ]
EOF

しかし、ターミナル(gnome-terminal内のtmux)で実行すると、 ANSIエスケープ文字\形式で出力されます。例えば、

\e[33mWarning\e[0m This scr....

色付けしたい部分をヒアドキュメント外のprintfコマンドに移動すると機能します。たとえば、これは動作します:

printf "${yellow}Warning:${normal}"
cat <<- EOF
    This script repo is currently located in:
    [ more messages... ]
EOF

man bashから–ここのドキュメント:

Wordに対して、パラメーターおよび変数の展開、コマンド置換、算術展開、またはパス名展開は実行されません。 Word内の文字が引用符で囲まれている場合、区切り文字Word、およびhere-documentの行は展開されません。 Wordが引用符で囲まれていない場合、ヒアドキュメントのすべての行は、パラメータ展開、コマンド置換、および算術展開の対象になります。後者の場合、文字シーケンス\ <newline>は無視され、\を使用して文字を引用する必要があります\$、および`

これがANSIエスケープコードにどのように影響するかを理解できません。 cattedされているBash hereドキュメントでANSIエスケープコードを使用することはできますか?

7
the_velour_fog

スクリプトでは、これらの割り当て

normal='\e[0m'
yellow='\e[33m'

これらの文字を文字通りに変数に入れます。つまり、 \e[mエスケープシーケンスではなく。 printf(または一部のバージョンのecho)を使用してエスケープ文字を作成できます。たとえば、

normal=$(printf '\033[0m')
yellow=$(printf '\033[33m')

ただし、tputを使用するほうがはるかに適切です。これは、正しく設定されたすべての端末で機能するためです。

normal=$(tput sgr0)
yellow=$(tput setaf 3)

あなたの例を見ると、あなたが使っているprintfのバージョンは\eエスケープ文字として(システムで機能する可能性がありますが、一般に他のシステムに移植できません)。これを確認するには、

yellow='\e[33m'
printf 'Yellow:%s\n' $yellow

literal文字が表示されます。

Yellow:\e[33m

エスケープシーケンスではなく。それらをprintf形式で配置すると、printfがそれらを解釈できるようになります(可能な場合)。

参考文献:

24
Thomas Dickey

この割り当ては、変数にエスケープ文字を配置していません。

normal='\e[0m'                  yellow='\e[33m'

そのためには、echo -eprintfまたは$'...'(bash)。

Bashを使用しているので、これを使用することもできます。

normal=$'\e[0m'                 yellow=$'\e[33m'

$文字列の前に'\e[0m'

ただし、エスケープされた文字を取得するポータブルな方法は、次のようにprintfです。

normal="$(printf '\033[0m')"    yellow="$(printf '\033[33m')"

エスケープ文字の8進数値(033)は、すべてのPOSIXシェルで有効です。

2
user79743