echoコマンドの使い方について語る

こんにちは。株式会社フィックスポイントのよしだです。

今回は、エンジニアの tennashiさんより、 echo コマンドの使用方法について勉強会にて発表がありました。

echo と言うと、画面に文字列を出すためのもの、というイメージが強い方もいらっしゃるかもしれません。

しかし、echo には文字列を出現させるに留まらない機能がありますので、ぜひ本記事を機に活用してみてください。

 

echoって?

本題に入る前に、echo をよくご存知ない方のために概要を説明します。

echo とは、ざっくり言うと引数の文字列を出力するためのコマンドです。
下の例を見ると分かるように、入力された文字列 hoge をそのまま標準出力に表示しています。

$ echo "hoge"
hoge

冒頭でも触れたように、この echo コマンドは"そのまま" 表示するだけではなく、他にも様々な効果を付けることが可能です。

 

エスケープシーケンスを使用した表現

エスケープシーケンスというものを使用すると、ただ表示する以外のことも可能になります。

いくつかの例を基に、見ていきましょう。

1.改行

まずはこちらを例として説明します。

$ echo -e "hoge\nfuga"
hoge
fuga

そのまま見て取れるように、hoge\nfuga ではなく hoge と fuga が改行されて表示されています。

上記を説明するには、2つの要素に注目する必要があります。

1点目として、コマンドの中に -e というオプションが入っているのが分かりますでしょうか。

この -e が一つのポイントとなります。

もし、上記コマンドから -e を抜くと、このようになります。

$ echo "hoge\nfuga"
hoge\nfuga

一番最初の説明のように、改行ではなく hoge\nfuga という文字列がそのまま表示されています。
つまり、この -e というオプションの有無が、改行ができるかという部分に関わってきます。

続いて2点目、もうお気付きかとは思いますが、hoge\nfuga の中に \n という文字が入っています。

これこそが、本項でのキーとなるエスケープシーケンスと呼ばれるものです。

 \n のような、 \ から始まる一連の(特定)文字列(=エスケープシーケンス)を出力すると、画面描写を操作できるようになります。

今回の \n は改行する、ということを意味しています。
hoge\nfuga は hoge \n fuga と解釈された結果、hoge と fuga が改行されて表示されたという訳です。

そして、先程の -e オプションとは、このエスケープシーケンスをただの文字列ではなく、エスケープシーケンスとして処理しますよ、というためのものです。
そのため、 -e がカットされていると hoge\nfuga がそのまま文字列として表示されてしまうのです。

f:id:aqui_jasmine:20211208151157p:plain

2.文字色の変更

さて、エスケープシーケンスを使用すれば、改行以外にも様々なことが可能です。

続いては、少し複雑な文字色の変更について紹介します。

$ echo -e "\e[31mhoge\e[0mfuga"
hogefuga

上記はコードブロックなので正しく表現できていませんが、実際には hogefuga のように表示されます。

今回の場合、描画されているのは hoge と fuga なのでそこを除いた部分がエスケープシーケンスです。*1

すると、 \e[31m と \e[0m というエスケープシーケンスが出てくるのではないでしょうか。

改行の際と異なり、大分長くなったことが見て取れます。
今回のような "長い" エスケープシーケンスには、多様なカテゴリが存在しています。
これらを読むときには、 "どのカテゴリの" "何番" なのか(さらにパラメータがある場合もあります)、と分解して解釈すると理解しやすいかと思います。

f:id:aqui_jasmine:20211208154226p:plain

それでは、今回も分解していきましょう。

今回の場合は、 \e[*m が文字装飾のカテゴリを、31 や 0 が実際の処理内容を示しており、m はシーケンス終端の目印にもなっています。*2

実際の処理である 31 と 0 に着目してみます。

まず 31 では、 3 が文字の色(foreground color) を変更することを、1 が色を赤にすることを示しています。

つまり、\e[31mhoge  は、「 hoge という文字について、文字色を赤にして表示してください」というコマンドになります。

ちなみに他にもご紹介すると、 3 のところを 4 にすると背景色(background color) を変更するという意味に変わります。また、1 を 2 にすると緑色を指定したことに変わります。

続いて 0 では、ここまで指定してきた描画の変更を全部リセットする、という意味を示しています。

 そのため、 \e[0mfuga では、「 fuga という文字について、前まであった指定(文字色を赤にする)をやめて表示してください」というコマンドになります。

3.複雑なエスケープシーケンス

先にちらっと記載しましたが、パラメータがある場合についても見てみましょう。

$ echo -e "\e[38;2;255;0;0mhoge\e[0mfuga"
hogefuga

これも先程と同様に hogefuga のように表示されるかと思います。

さっきと同じじゃない…?という方もいらっしゃるかと思いますが、今回は "真っ赤" というパラメータを指定した状態です。

今回注目すべきは、 \e[38;2;255;0;0m です。

\e[*m の部分は前と同じ意味ですので、中の 38;2;255;0;0 を分解していきましょう。

頭の 3 も前項と同じく文字の色を変更するという意味です。
次の 8 が今回のポイントとなります。

 8 のコマンドについて詳細な話に入る前に、端末上で表示できる色のパレットについて説明します。

パレットにはいくつか種類があり、下記の通り分かれています。

    • 8色(3bit): 黒マゼンタシアン
    • 16色(4bit): 上記8色各々の明度を上げたものを加える
    • 256色(8bit): 中間色を加えた
    • TrueColor(24bit): いわゆる #RRGGBB で表現できる色

3 のあとに続く数字が 0 - 7 の場合は、3bit color を指定したものと解釈され、各数字に当てはまる色が指定されます。

4bit color はこれまでと異なり、頭を 9 にしたあと 0 - 7 を入れて 3bit color と同様に指定します。

 3 のあとに 8 が続くと 8bit または 24bit の拡張を利用していると解釈され、どちらであるかは更に続くパラメータで指定されます。

今回は、 8 が指定されているので 8bit または 24bit のパラメータ指定が続くということになります。

エスケープシーケンスのパラメータは ; または : を挟むことで指定できます。

どちらに対応しているかは利用している端末に依るので、実際叩いてみて確認してみてください。*3

ここまでで、 \e[38;2;255;0;0m を解釈するための道具はそろったので、内容を紐解いて行きましょう。

  • \e[*m : カテゴリ指定
  • 3: 文字色変更
  • 8: 8bit or 24bit 拡張を利用
  • 2: 24bit 拡張を利用(8bit 拡張の場合は 5 になる)
  • 255: R 値
  • 0: G 値
  • 0: G 値

以上のことから、 #ff0000 で文字が表示されたという訳です。

f:id:aqui_jasmine:20211208174707p:plain

参加者の反応

今回の発表を聞いた参加者の反応です。

この発表をきっかけに興味が出てきた人もいるようですね!

思い思いの感想をSlackに書き込んでいます😊

f:id:aqui_jasmine:20211216102708p:plain

最後に

今回は、echo コマンドの様々な活用方法についてご紹介しました。

もっと複雑な内容も勉強会では扱いましたので、続いての記事に記載する予定です。

echo コマンドに興味のでた方は是非ご覧になってみてください!

echo コマンド応用編はこちら

 

 

株式会社フィックスポイントでは、一緒に働いてくれるメンバーを募集しています!

詳細は、こちらをご覧ください。

*1:描画を消すためのエスケープシーケンスや、順番を入れ替えたりできるエスケープシーケンスも存在するので、常にこの方法を使用する訳ではありません。

*2:詳細には、`\e[*m`はさらに分解できて、`\e[`は Control Sequence Introducer、`\e[*m`で Select Graphic Rendition というカテゴリであることを示しています。

*3:VImmer かつ TrueColor 利用者にはお馴染の設定値、`t_8b`/`t_8f` はこのパラメータ区切り文字がどちらであるのかを vim に教えるためのものです。