株式会社コーソル

コーソルDatabaseエンジニアのブログ

技術ブログ

xterm-color.sql, xterm-color256.sql from TPT Script : SQL*Plusでカラー表示

このエントリは (全部俺) Oracle ACE Director Tanel Poder Advent Calendar 2013 24日目の記事です。

これまで23個のエントリを書いてきましたが、Advanced Oracle Troubleshooting Guideの翻訳を中心にディープの話が多かったので、軽めな話題を取り上げたいと思います 🙂

xterm-color.sql

このスクリプトはSQL*Plusからカラー表示のエスケープシーケンスを出力することで、問合せ結果をカラー表示するものです。

私はUNIX端末に特に詳しいわけではないので、誤ったことを言っていたら申し訳ないのですが、ANSI標準では端末でカラー表示するためのエスケープシーケンスが定義されているようです。

具体的には、"ESC [ 値;...;値m"という文字列を与えると、カラー表示できます。 "値"には以下の数値を指定します。

Text attributes
0 All attributes off
1 Bold on
4 Underscore (on monochrome display adapter only)
5 Blink on
7 Reverse video on
8 Concealed on

Foreground colors
30 Black
31 Red
32 Green
33 Yellow
34 Blue
35 Magenta
36 Cyan
37 White

Background colors
40 Black
41 Red
42 Green
43 Yellow
44 Blue
45 Magenta
46 Cyan
47 White

したがって、SQL*Plusでカラー表示したい場合、上記のカラー表示のエスケープシーケンス文字列を、問合せの結果と返せばOKです。なお、"ESC"は制御記号であり、通常の文字のように'...'で指定できないため、chr(27)の結果として指定します。chr()は文字コードを引数にとり、対応する文字を返す関数です。

例えば、以下のコマンドを実行すると、問合せ結果の文字色を赤(=31)にできます。

SELECT chr(27)||'[31mTest' || chr(27)||'[0m' red_text FROM DUAL;

"["と"m"の間には、";"区切りで背景色や文字修飾を指定できます。例えば、以下のコマンドを実行すると、黄色の背景色(=43)と太字(=1)を指定できます。

SELECT chr(27)||'[1;31;43mTest' || chr(27)||'[0m' bold_red_text_with_blue_bg FROM DUAL;

ansi_color.jpg

xterm-color.sqlは階層問合せで、文字色と背景色について8色の組み合わせ、すなわち64通りの組み合わせを表示します。

xterm-color.jpg

余談ですが、ちょっと意図がわからないのが、上記出力の後半部分に相当するxterm-color.sqlの以下の箇所です。

  : 
select
    chr(27)||'[32m'||chr(27)||'[1;'||to_char(rownum+29)||'mTest' a
 ,  chr(27)||'[33m'||chr(27)||'[1;'||to_char(rownum+29)||'mTest' b
 ,  chr(27)||'[34m'||chr(27)||'[1;'||to_char(rownum+29)||'mTest' c
 ,  chr(27)||'[35m'||chr(27)||'[1;'||to_char(rownum+29)||'mTest' d
 ,  chr(27)||'[36m'||chr(27)||'[1;'||to_char(rownum+29)||'mTest' e
 ,  chr(27)||'[37m'||chr(27)||'[1;'||to_char(rownum+29)||'mTest' f
 ,  chr(27)||'[38m'||chr(27)||'[1;'||to_char(rownum+29)||'mTest' g
 ,  chr(27)||'[39m'||chr(27)||'[1;'||to_char(rownum+29)||'mTest' h
from dual
    connect by level<=8
    :

文字色の指定となる32~39の値を指定していますが、あまり意味があるとは思えないのですが・・・ もし意図が分かる方がいらっしゃったら、こっそり教えてください。:-)

xterm-color256.sql

xterm-color.sqlは8色のカラー表示をデモするスクリプトでしたが、xterm-color256.sqlは256色(本当は216色、詳細は後述)のカラー表示をデモするスクリプトです。

UNIX端末に特に詳しいわけではないので、誤ったことを言っていたら申し訳ないのですが、XTermでは256カラー表示するためのエスケープシーケンスが定義されているようです。

具体的には、"ESC [ 38;5;値m"という文字列を与えると、256色カラー表示できます。また、"ESC [ 48;5;値m"という文字列を与えると、背景を256色カラー表示できます。 "値"には以下の数値を指定します。

  • 0-15 : システムカラー
  • 16-231 :6x6x6 RGB カラー。 r,g,b = [0..5] として、((36 * r) + (6 * g) + b + 16) で与えられる。
  • 232-255 : 白と黒以外のグレースケール

xterm-color256.sql は、16-231の範囲の6x6x6 RGB カラーを一覧表示します。したがってファイル名に反して、実際には216色を表示します 😛 。

xterm-color256.sql の実装は、すこし工夫が凝らされています。

[oracle@l64rw3 ~]$ cat sql/demos/xterm-color256.sql
-- oracle 11.2+

SELECT
  LISTAGG (CHR(27)||'[48;5;'|| <== (*3)
              ( 16 + MOD(r,6) + MOD(TRUNC(r/6),6)*6 + MOD(TRUNC(r/36),6)*6*6 )||'m'|| <== (*2)
              LPAD(16 + MOD(r,6) + MOD(TRUNC(r/6),6)*6 + MOD(TRUNC(r/36),6)*6*6,4)||
              CHR(27)||'[0m'
  ) WITHIN GROUP (ORDER BY MOD(TRUNC(r/6),6)) <== (*3) 
FROM
    (SELECT rownum r FROM dual CONNECT BY LEVEL <= 216) <== (*1)
GROUP BY
    MOD(TRUNC(r/36),6) <==(*3)
/

(*1)の箇所でで1~216の結果セットを得て、(*2)の箇所で16 + Green + Blue + Redの色コードを得ています。(*3) の LISTAGG ( ... ) WITHIN GROUP (ORDER BY MOD(TRUNC(r/6),6)) GROUP BY MOD(TRUNC(r/36),6)の箇所で、Red系列(MOD(TRUNC(r/36),6))でグループ化して、LISTAGG() 分析ファンクションで文字列結合しています。LISTAGG() は11.2より導入された、複数行の文字列を文字列結合する分析ファンクションです。イメージとしては、スクリプト言語のjoin()に近い動作をします。(よけい分かりにくい? :-P)

実行結果は以下のようになります。なかなかカラフル!

xterm-color256.jpg

プロフィール

On7tWW6m1Ul4

渡部 亮太

・Oracle ACE
・AWS Certified Solutions Architect - Associate
・ORACLE MASTER Platinum Oracle Database 11g, 12c 他多数

カテゴリー

アーカイブ