はじめに
この記事は
既にある優れた記事などを読んで、自分で理解したこと&試したことをまとめました。
「手っ取り早く色変えたいんだよ!」という方は参考記事をご覧ください。
動機
毎回新しい環境を作るたびにググってたので、いいかげんちゃんと調べようと…
検証環境
Acer Chromebook 11 CB311-8H-C5DVのcrouton(crosh)とcrostini(標準ターミナル)。どっちもDebian(stretch)。
結論
\[ ... \]
とは
bashプロンプトで使用できる特殊文字
\[
非表示文字のシーケンスの開始。 これを使うと、プロンプト中に端末の制御シーケンスを埋め込むことができます。
\]
非表示文字のシーケンスを終了します。
参考:
\033[01;34m
とは
ANSI escape codeの中でCSI(Control Sequence Introducer) sequencesに含まれるSGR (Select Graphic Rendition) の指定(今回のメイン)
参考:
まずは\[ ... \]
を消せ!
Linuxを触り始めて慣れてくると「プロンプトのデザイン変えたろ!」という欲求はだれもが持つものでしょう。
そしておもむろに~/.bashrc
などを開き、
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
みたいな記述を見た瞬間「あっ、とりあえずコピペでいいや…」となったことでしょう(反省)。
そんなだらしない自分から脱却するため、今回ちゃんと調べてみました!
差し当たって、初見でやる気を削いでくるこの妙ちくりんな記述を分解してみます。
上の「結論」でも述べたとおり、\[\033[01;34m\]
は\[ ... \]
と\033[01;34m
に別れます。
そして\[ ... \]
は上述の通り非表示文字のシーケンスを表しますが、少なくとも私の環境ではなくても何の問題もありませんでした。ので、こいつは思い切って削除しちゃってもいいと思います。
推測ですが、カラーに対応していないターミナルアプリケーションなんかの場合に\033[01;34m
が文字列として出力されるのを防ぐため(JavaScriptをHTMLのコメントで囲うみたいな?)かなーと考えましたが、~/.bashrc
では以下のような処理で振り分けてますし、正直存在意義が分かりません。お前のせいで見づらかったんだよ!
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
さぁ、これで残りは\033[01;34m
だけ!だいぶ分かりやすく…なってない😓
\033
ってなんだ?
ずばりエスケープシーケンス(の一部)です。
エスケープシーケンスといえば、例えばC言語でハローワールドする以下のコードの、
#include <stdio.h>
int main(){
printf("Hello, World!\n");
}
\n
もエスケープシーケンスです。
改行の場合には"n"という愛称文字が当てられていますが、改行を表す文字コードを記述しても同様に動作するのはご存知の通りでしょう。
#include <stdio.h>
int main(){
printf("Hello, World!\n");
printf("Hello, World!\x0A"); // 16進数
printf("Hello, World!\012"); // 8進数
}
そうです、お気づきの通り\033
も何らかの意味を持つ文字コードを8進数で記述したものなのです。
そしてその意味はアスキーコード表などを見ればすぐ分かりますが、
**ESC(エスケープ)**です。
まんまやん!エスケープシーケンスだからね!
となると当然「改行は\n」のように愛称文字があるのではないかという疑問が湧くと思いますが、
\eです。
まんまやん!ESCのeね!
という訳で\033[01;34m
は\e[01;34m
と書き換えられます。またちょっと見やすくなりました。
\e[...m
の構文で記述する
で、まとめるとフォントの色やスタイルの指定は\e[...m
の構文で記述することになっています。
ここでパラメーターは;
で区切って複数併記することができます。
従って繰り返し登場している\e[01;34m
は、
\e[01m
:ボールド(bold)をセット
と
\e[34m
:フォアグラウンドを青にセット
に分解できます。
指定できるパラメーターは参考記事やMan page of CONSOLE_CODESをご覧ください。
プロンプトだけじゃない!
grep
やls
コマンドでもフォントカラーが変わったりするので、考えれば当然なのですが、例えば以下のようにターミナルで変数に代入する場合にも使えたりします。
$ var='\e[41mH\e[42mE\e[43mL\e[44mL\e[45mO\e[46m!\e[m'
$ echo -e $var
ちなみにecho
コマンドでエスケープシーケンスを解釈させるには-e
オプションを付けます。
-e バックスラッシュによるエスケープを解釈する
256色指定
色関連であといくつか。
ESC[ 38;5;⟨n⟩ m
:foreground color
ESC[ 48;5;⟨n⟩ m
:background color
の構文で256色の指定ができます。nの数字と色の対応は以下の通り。
0- 7: standard colors (as in ESC [ 30–37 m)
8- 15: high intensity colors (as in ESC [ 90–97 m)
16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
232-255: grayscale from black to white in 24 steps
参考:ANSI escape code - Wikipedia
実行してみるとこんな感じ。
#!/bin/bash
for i in {0..15}
do
for j in {0..15}
do
((c = i * 16 + j))
printf "\e[38;5;%dm%02X " $c $c
done
echo ""
done
rgb(トゥルーカラー)指定
ESC[ 38;2;⟨r⟩;⟨g⟩;⟨b⟩ m
:Select RGB foreground color
ESC[ 48;2;⟨r⟩;⟨g⟩;⟨b⟩ m
:Select RGB background color
せっかくなのでグラデーションを作ってみました。
#!/bin/bash
for r in {32..0}
do
((b = 32 - r ))
for g in {0..32}
do
printf "\e[48;2;%d;%d;%dm " $((r<<3)) $((g<<3)) $((b<<3))
done
echo ""
done
もういっちょ。
#!/bin/bash
rgb_curve(){
x=$1
((x %= 192))
if (($1 < 0)); then
((x += 192))
fi
if ((x <= 0)); then
return 0
elif ((x < 32)); then
return $(((x << 3) - 1))
elif ((x < 96)); then
return $(((16 << 4) - 1))
elif ((x < 128)); then
return $((((128 - x) << 3) - 1))
elif ((x < 192)); then
return 0
fi
}
for i in {1..32}
do
for j in {-32..160}
do
rgb_curve $((j - 64)); r=$?
rgb_curve j; g=$?
rgb_curve $((j + 64)); b=$?
printf "\e[48;2;%d;%d;%dm " $r $g $b
done
echo ""
done
echo -e "\e[m"
もうちょっと関数キレイにしたいですね…
以上!
参考記事
- Qiita記事
-
ANSIエスケープコード - コンソール制御 - 碧色工房
- 大変参考になりました。ターミナルで画像のプレビューやってみたい。
-
サーモグラフィ風の色変化をシグモイド関数で再現する - Qiita
- color2.shで雰囲気だけ参考にしました。shellscriptでは無理だ…。
- その他