sentaku というシェルスクリプトのツールをアップデートしている時に、 文字列のハイライト部分を変換したいことがあったのでそのメモ。
シェルスクリプトでの文字列の装飾
printfのコマンドで文字列を出力する際、
printf "\e[7maaa\e[m"
とすると、aaaをバックグランドと文字色を反転させて表示させる事が出来ます。
(文字列はクォートで囲う必要あり。)
ここで最初の\eはエスケープで[とmで挟まれた7の数字がこの反転を指定しています。
| N | 表示 |
|---|---|
| 0 | デフォルト |
| 1 | 太字(Bold)、または強調表示 |
| 2 | 薄く表示、もしくはsecond colorの指定があればそれ |
| 3 | イタリック |
| 4 | アンダーライン |
| 5 | ゆっくり点滅 (<150/分) |
| 6 | 素早く点滅 (%gt;150/分) |
| 7 | 反転表示(negative image) |
| 8 | 非表示(パスワードなどを隠すのに使える) |
| 9 | 取り消し線 |
などがあります。また、 30-37を使うとそれぞれ、黒、赤、緑、黄色、青、赤紫、青緑、白の文字色にでき、 40-47を使うと背景色をそれらの色に出来ます。
複数使うときは;でつなげて
printf "\e[1;31;42maaa\e[m"
とすれば太字で、背景緑、文字色赤に出来ます。
また、
printf "\e[38;05;121maaa\e[m"
の様に、38;05;を指定すると、その後に256色に割り当てられた番号を指定できます。
最後にリセットするために\e[m(番号指定なし)を入れてあります。
また、\eの部分はエスケープを表していますが、これは
\033(8進法)または\x1B(16進法)でもOK。
またCtrl-V Escを押すことでエスケープキーを挿入して
代わりに使うことも出来ます。(表示上は^[となります。これを直接打ってもダメ。)
sedで削除する
削除するには以下の様な感じ:
printf "\e[31maaa\e[m"|sed "s/^[\[[0-9;]*m//g"
後ろの^[で始まってmで終わる文字列で中に数字か;が入っている部分を削除しています。
Ctrl-V Escで入力しています。 (上のを直接コピペしても上手くいきません。)
出力の際に\eとかでもprintfで出力した時点でエスケープ文字となるので
エスケープ文字で直接。
[は返還前の所ではエスケープする必要があります。
追記: 2016/05/29
通常、ハイライトを付けるときは、\e[7mみたいな最後がmで終わる形になっていますが、
grepで色を付けて
printf "a" | grep --color=always -i "a" > log
これでlogのなかを見ると
^[[01;31m^[[Ka^[[m^[[K
こんな感じで\e[Kが各ハイライトの文字列に追加されて付いています。
ちょっと調べてみてもパッとこのKのオプションが良くわからなかったのですが、
取り敢えずあってもなくてもちょっとやってみた感じでは同じでした。
これがちょっと問題になるのが、
$ x=$(printf "a" | grep --color=always -i "a")
$ echo ${#x}
18
$ y=$(printf "$x"|sed "s/^[\[[0-9;]*m//g")
$ echo ${#y}
4
みたいにしてハイライト部分を覗いた実際の文字列の数を数えたい時、
このままだとKの部分が邪魔して間違った答えが出ます。
(aだけなので1になってほしい。)
なのでそれも除いて
$ z=$(printf "$x"|sed "s/^[\[[0-9;]*m//g"|sed "s/^[\[K//g")
$ echo ${#z}
1
とすればOK。
追記ここまで
sentaku
上の変換はsentakuの中で色付きの文字列を扱う時に必要になったものです。
sentakuは複数の文字列を入力に渡して、 対話的に選択して選択したものを出力させるものです。
シェルスクリプトでできているので大概のところで動くと思います。 (BashでもZshでも。)
もともと別のスクリプトを作っている時に 対話的に出力を選択したい時があってその時に作ったものを取り出したもので 関数などを使うことで拡張できる様にしてあります。
また、
sentakuのレポジトリにある
ddv
は2つのディレクトリのdiffをとって違いのあるファイルを一つ一つvim -dしていくスクリプトで
自分では結構使っています。
