エスケープシーケンスによる画面制御

2019/03/08更新

目次

概要

LinuxやCygwinなどのターミナル環境では、制御文字の1つであるエスケープ(\e\x1b)を出力することで、文字色の変更やカーソル移動が行なえる。

一覧

カーソル移動

文字

効果

\e[nA

カーソルを上にn移動

\e[nB

カーソルを下にn移動

\e[nC

カーソルを右にn移動

\e[nD

カーソルを左にn移動

\e[nE

カーソルをn行下の先頭に移動

\e[nF

カーソルをn行上の先頭に移動

\e[nG

カーソルを左端からnの場所に移動(左端が1)

\e[n;mH

カーソルを上端からn、左端からmの場所に移動(左上が1,1)

\e[0J

画面のカーソルより後ろを消去(0は省略可)

\e[1J

画面のカーソルより前を消去

\e[2J

画面全体を消去

\e[0K

その行のカーソルより後ろを消去(0は省略可)

\e[1K

その行のカーソルより前を消去

\e[2K

その行全体を消去

\e[nS

画面をn行次にスクロールする

\e[nT

画面をn行前にスクロールする

  • nmは整数。省略時は1。

文字装飾

文字

効果

\e[0m

文字の装飾をリセットする

\e[1m

太字にする(TeraTermなどでは強調色表示となる)

\e[2m

薄文字にする ※

\e[3m

斜体にする ※

\e[4m

下線を引く

\e[5m

点滅させる(TeraTermなどでは色が変化する)

\e[6m

高速で点滅させる ※

\e[7m

反転させる(前景色と背景色を入れ替える)

\e[8m

画面に表示させない(コピーはできる)

\e[9m

取り消し線を引く ※

\e[3Xm

文字色を変更する(Xは色番号)

\e[39m

文字色をデフォルトに戻す

\e[4Xm

背景色を変更する(Xは色番号)

\e[49m

背景色をデフォルトに戻す

\e[9Xm

文字色を変更する(Xは色番号、30番台より強い色) ※

\e[10Xm

背景色を変更する(Xは色番号、40番台より強い色) ※

  • ※は、対応していないターミナルが多い、もしくは非標準のもの。

  • 最後に\e[0mでリセットしないと、出力終了後も影響が残ったままとなってしまうので注意。

  • 色番号は、0=、1=、2=、3=、4=、5=マゼンタ、6=シアン、7=

  • 複数を一度に指定する場合は、例えば\e[1;4;31m(太字、下線、赤)のように;で区切る(環境によってはできない)。

使用例

文字の装飾や強調

画面に大量のログ出力をする場合など、ログレベルのラベルやタグを強調表示したり、ログ中のファイルパスやURLの色を変えたりするだけで、格段に見やすくなる。

use Time::HiRes;

# あらかじめ装飾を施したフォーマットを用意しておく
my $INFO = "\e[32m\e[1m[INFO]\e[0m \e[32m%s\e[0m\n";
my $WARN = "\e[31m\e[1m[WARN]\e[0m \e[31m%s\e[0m\n";

for (my $i = 0; 1000 > $i; $i++) {
    my $val = int(rand(10));
    if ($val > 0) {
        printf $INFO, '出力しています。';
    } else {
        printf $WARN, '警告があります。';
    }
    Time::HiRes::sleep(0.1);
}

上記のプログラムを実行すると、以下のように出力される。

$ perl hoge.pl
[INFO] 出力しています。
[INFO] 出力しています。
[INFO] 出力しています。
[WARN] 警告があります。
[INFO] 出力しています。

進捗状況の表示

以下は0.1秒ごとに1行の出力を行なうPerlプログラムであるが、処理時間が長くなるため、常に最下行に目立つように現在どこまで進んでいるかの進捗状況を表示しておきたい。そのような場合に、カーソル移動や文字装飾が利用できる。

use Time::HiRes;
$| = 1; # バッファリングしないようにする(後述)

my $output_num = 1000;
for (my $i = 1; $output_num >= $i; $i++) {

    # \e[2Kを出力して、その行をクリア。
    print "\e[2K";

    # 1行出力して改行する。
    print "これは$i番目の出力行です。\n";

    # 目立つように太字で色を反転させて進捗状況を出力する(最後に装飾をリセットする)。
    print "\e[1m\e[7m $i / $output_num が完了しました。\e[0m";

    # \e[1Gでカーソルを先頭に戻しておくことで、次の行に上書きして消してもらう。
    print "\e[1G";

    Time::HiRes::sleep(0.1);
}

上記のプログラムを実行すると、以下のように出力される。

$ perl hoge.pl
これは1番目の出力行です。
これは2番目の出力行です。
これは3番目の出力行です。
これは4番目の出力行です。
これは5番目の出力行です。
 5 / 1000 が完了しました。

独自の表を作成

画面上の任意の位置から出力できるので、表のような出力も簡単にできる。

my $head = "\e[8GAAA\e[16GBBB\e[24GCCC\n";
my $line = "%s\e[8G%d\e[16G%d\e[24G%d\n";

print $head;
printf $line, 'XXX', 1111, 2222, 3333;
printf $line, 'YYY', 4444, 5555, 6666;
printf $line, 'ZZZ', 7777, 8888, 9999;

上記のプログラムを実行すると、以下のように出力される。

       AAA     BBB     CCC
XXX    1111    2222    3333
YYY    4444    5555    6666
ZZZ    7777    8888    9999

注意点

ハマり所

  • プログラムが出力をバッファリングすると効果が出なくなることがある。例えば、Perlであれば、スクリプトの先頭で「$| = 1;」としておくことでバッファリングを回避する。

  • エスケープによるカーソル移動や文字装飾は、ターミナル画面に出力したときしか効果が無い。ファイルなどに出力すると、効果が無いばかりか、余計な制御文字をファイルに混入させてしまうため、出力先がターミナルかファイルかによって、出力を分ける必要が出てくる。

  • エスケープによる文字装飾を施した文字列をパイプでlessコマンドに渡すと、エスケープ文字がそのまま表示されてしまい、効果が出ない。これは-Rオプションを使うことで回避できる。

    echo $'\e[31m赤い文字列\e[0m' | less -R
    

外部リンク