• ANSI Terminal Echo

Windowsでは、コンソールアプリケーションから画面を制御するには、コンソールAPIを使うことになっているが、UNIX/Linuxでは、エスケープシーケンス(エスケープコード、コントロールシーケンスなどとも呼ぶことがある)で制御するのが普通だ(写真01)。エスケープシーケンスとは、もともとは端末装置のための制御コードで、ANSI(American National Standards Institute。米国標準協会)がANSI X3.64(1979年)として規格化したことにちなみ、ANSIエスケープシーケンスと呼ばれることがある。また、この規格に準拠した旧DEC社の端末装置VTシリーズが広く使われたことからVTエスケープシーケンスとも呼ばれる。なお、ANSI X3.64とECMA-48(1976年。ヨーロッパの規格)は、ほぼ同じである。その後、これらの規格は、ISO/IEC 6429として国際規格となった。

  • 写真01: エスケープシーケンスによるテキストの表示。Linux(中央緑色のプロンプト)やPowerShell(下部。白いプロンプト)はEscコードを文字列に挿入できるため、簡単にANSIエスケープシーケンスが使える。cmd.exe(ウィンドウ冒頭部分)は、組み込みコマンドではEscコードを扱えないのでC#でコマンドを作った

エスケープシーケンスは、「Esc」コード(0x1B)を先頭に文字を組み合わせて、カーソルの制御などを行う。その他、文字の色や属性(イタリック、下線、反転、点滅、高輝度など)を指定できる。エディタなどアプリケーションからの本格的な利用には、UNIX/Linux系ではncuresなどのライブラリを利用するが、スクリプトで文字にちょっと色をつけたいなんて場合には、文字列中に直書きすることがある。このときに利用するエスケープシーケンスにはSGR(Select Graphic Rendition)という名称がある。現在でもエスケープシーケンスを区別するためにANSI X3.64などで付けられた名前を使うことが多い。

基本的な形式は、「\e[<パラメータ>m」となる。UNIX/Linux系では文字列にEscコードを埋め込むときエスケープ文字を使い\eと表記する。にはASCIIコードの数字文字を指定する。表01は、そのパラメータを示す数字だ。“[”と"m"の間には複数のパラメータを置くことができ、その場合には「;」で区切る。最新のISO/IEC 6429では、0~69まで定義してあるが、どれを実装するのかは、端末(端末ソフトウェア)次第。多くの場合、古いANSI X3.64程度になっていることも多い。なお、「\e[」の部分は、規格ではCSI(Control Sequence Introducer)と表記される。

  • 表01

たとえば、Linuxのbashなら「echo -e "\e[34mTest\e[0m"」とすれば、青色で文字が表示されるはずだ。先頭の「\e[34m」が文字色、青の指定で、末尾の「\e[0m」は属性のリセットである。これを忘れるとずっと色が変わったままになる。

複数の属性をまとめて記述するときには、「echo -e "\e[3;34;43mTest\e[0m"」とする。これは、文字を斜体にして文字が青、背景を黄色にするものだ。

PowerShellのWrite-Hostコマンドは、文字色を表示するためのオプションを持っているので、わざわざ色指定をエスケープシーケンスで行う必要はないが、オプションで指定できないイタリック表示などを行うなら、


write-host "This is $([char]0x1B)[3mItalic$([char]0x1B)[0m string"

とする。なお、PowerShell 7以降なら「$([char]0x1B)」の代わりにEscコードを表す「`e」が使える。

ANSI X3.64ではパラメータ“1”は、「太字または高輝度」と定義してあるが、高輝度で表示する端末ソフトが少なくない。というのは、太字にすると画面上での文字サイズが変化してしまうため、等幅フォントを使う端末エミュレーターでは扱いづらい。文字間隔を太字に合わせなければならず、通常文字の表示だと文字間隔があきすぎになってしまうからだ。というわけでこれを指定すると、ほとんどの端末ソフトで色が明るい色で表示される。また、SGRには低輝度“2”もあるので、


echo -e "\e[34m通常\e[1m高輝度\e[2m低輝度"

とすると、同じ青でも3段階の表示が可能になる(Windows Terminalの場合。もちろん端末依存である)。

残念ながらcmd.exeの場合、Escコードを文字列に入れるための記法がない。また、標準コンソールウィンドウ(conhostウィンドウ)は、デフォルトでは、エスケープシーケンスを解釈しないようになっている。このため、プログラムを作らないとエスケープシーケンスが利用できない。

Windowsでは、長らくWindows固有のコンソールAPIを使って画面制御を行うこととされてきたが、Windows 10でコンソールが改良されるとき、WSLでLinuxがエスケープシーケンスを使うため、ANSIエスケープシーケンスに対応した。Microsoftのドキュメントを見ると、今後は、エスケープシーケンスを使う方向になるようだ。1989年に開発が始まったWindows NTでエスケープシーケンスと手を切ったMicrosoftだが、結局エスケープシーケンスの利用に戻るようだ。ただ、Windowsには、ncursesのようなライブラリがないため、Windows 11では、このあたりを強化することになるだろう。

タイトルの元ネタは、Michael Crichtonの“The Terminal Man”にする予定だったが、あまりにありきたりなので考え直すことにした。そこで思い出したのが「ターミナルエコー」だが、これはかつてJR吉祥寺駅にあった駅ビルの名前。そもそもターミナルとは、ローマ神話のテルミヌス神が語源。国境にテルミヌスにちなむ石を置いたため、後年「末端」、「境界」の意味を持ち、駅や空港を表す言葉になった。端末装置もここから来ており「The Terminal Man」は、コンピュータとの関係から付けられた題名だ。同じ名前で1974年に映画化されたが、邦題は「電子頭脳人間」だった。なお、同名の小説は、もう1つあり、こっちは、空港に住むことを余儀なくされた人の自伝。スピルバーグの映画Terminal(邦題はターミナル)の元になった。Echoは木霊の意味だが、ギリシャ神話の妖精の名前でもある。最近の若い人には、端末ソフトやエスケープシーケンスなどは、もう「神話」時代の話なのかもしれないが。