vorfee's Tech Blog

Just another tech blog

ターミナルのechoやprintfに256色で色をつける 完全版

ターミナル出力に色をつける方法を調べた。

文字に色をつける方法

echo-eオプションをつけ、文字の前にある記号を書くと色がつく。printfの場合はオプションなどは必要なく普通に色がつく。

# 文字色の変更
echo -e "\e[30m黒色"
echo -e "\e[31m赤色"
echo -e "\e[32m緑色"
echo -e "\e[33m黄色"
echo -e "\e[34m青色"
echo -e "\e[35m赤紫色(マゼンタ)"
echo -e "\e[36m水色(シアン)"
echo -e "\e[37m白色"

# すべての変更をデフォルトに戻す
echo -e "\e[mデフォルトの色"

# さまざまな色を使用する
echo -e "\e[31m赤色\e[36m水色\e[mデフォルト\e[31m赤色\e[m"

# printfの場合
printf "\e[31m%s\n\e[m" "RED"

記号の意味

\e[31mのような記号はANSIエスケープシーケンスといい、意味で分解すると以下のようになる。

  • \e[ ... シーケンスエレメント
  • 36 ... 処理内容コード
  • m ... シーケンス終了を表すエンド・コード

エスケープシーケンスとは、コンピュータシステムにおいて、通常の文字列では表せない特殊な文字や機能を、規定された特別な文字の並びにより表したもの。

エスケープシーケンス - Wikipediaより)

仕組みの詳細はともかく、エスケープシーケンスを読み込んだターミナルは「おっ、これはただの文字じゃないな」と区別する。シェルではなくターミナルが処理するため、処理できるかどうかはターミナルの種別に依存する。

※ ちなみに\eはキーボードのESCキーを表しており、\eの代わりに\033(8進数形式のESC)や\0x1b\0x1B\x1b\x1B(どれも16進数形式のESC)も同じように使用できる。

処理内容コード(色の指定)

bash:tip_colors_and_formatting - FLOZz' MISC
http://misc.flogisoft.com/bash/tip_colors_and_formatting

上記のサイトが色付きで非常にわかりやすく紹介しているので参照されたし。

処理内容コードを変えることで8色から256色まで、さまざまな色を指定することができる。(ただしターミナルによっては256色を利用できない)

具体例

エスケープシーケンスを使って色を変える例を示す。

# 文字の色をblueにする
echo -e "\e[34m青い文字\e[m"

# 文字の色をblueにした後redにする
echo -e "\e[34mこれは青\e[31mこれは赤\e[m"

# 文字の色をblackにして背景をyellowにする
echo -e "\e[30;43m黒文字で黄背景\e[m"

# 文字を太字(強調)にする
echo -e "\e[1m太文字\e[m"

# 文字をmagentaにして太文字(強調)にする
echo -e "\e[35;1m極太マゼンタ\e[m"
echo -e "\e[1;35mこれも全く同じ\e[m"

# 文字と背景の色を反転する
echo -e "\e[7m反転する\e[m"

# 文字に下線を引く
echo -e "\e[4m下線付き\e[m"

# 下線を引いたり消したり
echo -e "\e[4m下線つき\e[m下線なし\e[4m下線つけるよ\e[m"

# ディム(薄暗く)する
echo -e "\e[2m最近髪が薄くなってきた\e[m"

ここまで読んで以下の出力がどうなるか頭の中で分かれば完璧。

echo -e "\e[7mAAA\e[33mBBB\e[m\e[31;1mCCC\e[m"

ここから下はおまけなので読まなくてよい。

別の方法 - tputコマンド

エスケープシーケンスを書く以外にも文字色を変更する方法がある。tputコマンドだ。

tputコマンド

tputはエスケープシーケンスを出力するコマンドである。tputの出力内容は、ターミナルエミュレータごとの仕様の違いを解決するためのファイル、terminfoに依存する。

terminfoファイルにはターミナルの機能に関する定義(エスケープシーケンスとターミナル機能の関連付け)がされている。tputはこの定義をコンソール上に直接出力するコマンドである。

繰り返すが、tputはエスケープシーケンスをターミナルに出力しているだけである。

tputの使い方

tputのusage。

usage: tput [-V] [-S] [-T term] capname

Options
    -V バージョン情報を表示
    -S まとめて処理
    -T ターミナルタイプ指定(e.g. tput -T xterm-8bit)
capname
    ncursesのドキュメントterminfo(5)を参照
    コマンド'man terminfo 5'で参照可能

capnameの一覧はman terminfo 5でマニュアルページを参照することで取得できる。capnameに設定されているエスケープシーケンスを得るにはinfocmpコマンドを使用する。

tputを使って文字色を変更する

文字色を操作するcapnameの定義はsetafである。おそらくSET Ascii Foregroundを意味している。

# 文字色を青くする
tput setaf 4 && echo "青い文字"

これは手動で以下を入力するのと同じことである。

echo -e "\e[34m青い文字"

tputを使って背景色を変更する

背景色を操作するcapnameの定義はsetabである。おそらくSET Ascii Backgroundを意味している。

# 背景を赤くする
tput setab 1 && echo "赤い背景"

これは以下と同意である。

echo -e "\e[41m赤い背景"

tputで指定できる色は0〜255の256通りである。0から7までは基本の8色、8から15までは明るい8色、16から255までが様々な色を指す。ただしデフォルト色に戻すcapnameは提供されていない。

tputを使ってターミナルを制御

色を変更する他に、ターミナルの制御もできる。capnameの中でも特にシェルスクリプトの役に立ちそうなものだけ紹介する。

capname エスケープシーケンス(xterm) 意味
cuu1 \e[A カーソルを一つ上に
cud1 \cj カーソルを一つ下に
cub1 \ch カーソルを一つ左に
cuf1 \e[C カーソルを一つ右に
civis \e[?25l カーソルを不可視に
cvvis \e[?12;25h カーソルを可視に
clear \e[H\e[2J ターミナルの画面をクリア
bel \cg ベルを鳴らす
# 前の行に上書きするように文字を出力する
tput cuu1 && echo "HOGEHOGE"

# 画面表示をクリア
tput clear

# ベルを鳴らす
tput bel

おまけ:zshなら簡単

zshなら簡単に文字色の変更ができる。

.zshrcに下記を追記するとzshにカラー機能が追加できる。

autoload -Uz colors
colors

colorsを読み込むと、下記のように色を名前で使用できるようになる。

# colorsで定義された色を使用する例
echo "${fg[red]}赤色文字"
echo "${fg_bold[blue]}青太文字"
echo "${bg[yellow]}${fg[black]}ああああ"
echo "${bg_bold[green]}緑背景太文字"
echo "${fg[yellow]}きいろ${fg[default]}デフォルト${fg[blue]}あお"

colorsは8色しか扱えないのが弱点だ。

更新

2016/Dec/22 全体の文章校正を変更。tputに関する情報を追加。

参照

https://www.grapecity.com/tools/support/powernews/column/clang/047/page02.htm

http://d.hatena.ne.jp/daijiroc/20090207/1233980551

http://ascii-table.com/ansi-escape-sequences.php

http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting

http://ja.wikipedia.org/wiki/%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9

http://www.cppll.jp/cppreference/ascii.html

http://misc.flogisoft.com/bash/tip_colors_and_formatting

http://www.ibm.com/developerworks/jp/aix/library/au-learningtput/

http://www.comptechdoc.org/os/linux/howlinuxworks/linux_hltermcommands.html

http://doda.b.sourceforge.jp/2013/01/03/termcap_andterminfo/

http://unix.stackexchange.com/questions/139018/what-is-the-difference-between-tputs-setf-and-setaf

http://www.manpagez.com/man/5/terminfo/