tput を理解する

UNIX シェル・スクリプトに少しスパイスを加える

UNIX® が持つ最も強力な資産の 1 つは、ユーザーにとって便利なようにシェル・スクリプトを作成できることです。シェル・スクリプトは、単純な 1 行のものから数千行に及ぶものまであり、多くの場合にメニュー・ベースのスクリプトへと進化し、スクリプトの作成者は単純にスクロールして表示するテキスト以上のものをユーザーに表示しようとします。また場合によると、単純な 1 行か 2 行の出力しかユーザーに表示されないシェル・スクリプトを作成することで、警告メッセージを強調したいと考えることもあります。スクリプトの複雑さによらず、スクリプトの作成者は常に、出力を太字にしたり出力に下線を引いたり、また強調表示を反転したりするための方法を必要としてきました。そうした場合に tput が活躍します。

Adam Cormany, National Data Center Manager, Scientific Games Corporation

Adam Cormany は現在 Scientific Games 社の National Data Center のマネージャーですが、過去数年間は同社の UNIX システム・エンジニアであり、UNIX 管理者であり、オペレーション・マネージャーでもありました。彼は AIX や Solaris、Red Hat Linux の管理に 10 年以上の深い経験があり、pSeries AIX システム管理の IBM eServer Certified Specialist です。またシステム管理の他に、BASH、CSH、KSH などのシェル・スクリプトや C、PHP、Perl でのプログラミングにも幅広い知識を持っています。



2008年 4月 01日

tput とは何か

tput コマンドは terminfo データベースを使ってターミナル・セッションの初期化と操作を行います。tput を利用すると、端末の機能のいくつかを変更することができます。例えばカーソルの移動や変更、テキストのプロパティーの変更、また端末画面の特定領域のクリアーなどが可能になります。


terminfo データベースとは何か

UNIX システムの terminfo データベースは、端末とプリンターの属性と機能を定義します (例えば各機器 (端末やプリンターなど) の行や列の数、そしてその機器に送信されるテキストの属性など)。UNIX で一般的に使われるいくつかのプログラム (vi や emacs などのエディター、curses や man などのプログラム等々) は、こうした属性やその他さまざまな用途に terminfo データベースを利用しています。


コマンドラインでの tput 入門

tput コマンドは他の大部分の UNIX コマンドと同様、シェル・コマンドライン、あるいはシェル・スクリプト内部のいずれかで使用することができます。tput をよく理解できるように、この記事ではコマンドラインから始め、その後でシェル・スクリプトの例に移ります。

カーソルの属性

UNIX のシェル・スクリプトやコマンドラインでカーソルを移動できたり、あるいはカーソルの属性を変更できたりすると便利です。パスワードなどの機密情報を入力する必要がある、あるいは画面上の 2 つの異なる場所に情報を入力する必要がある、といったことがよくありますが、そのような場合に tput が役に立ちます。

カーソルの移動

tput を使うと、対象の機器上でカーソルの位置を容易に移動することができます。tputcup オプション、つまり cursor position (カーソル位置) を使うと、その機器の行と列全体の任意の X 座標または Y 座標にカーソルを移動することができます。機器の最上部左端の座標が 0,0 です。

ある機器の 5 列目 (X) の 1 行目 (Y) にカーソルを移動するためには、単純に tput cup 5 1 を実行します。また別の例として、tput cup 23 45 はカーソルを 23 列目の 45 行目に移動します。

カーソルの移動と情報の表示

カーソルの位置に関する操作では、カーソルを移動し、コマンドを実行して情報を表示し、それから移動前のカーソル位置に戻る、といったこともできます。

(tput sc ; tput cup 23 45 ; echo “Input from tput/echo at 23/45” ; tput rc)

このサブシェル・コマンドを分解してみましょう。

tput sc

まず、現在のカーソル位置を保存する必要があります。現在のカーソル位置を保存するためには、sc オプション、つまり「save cursor position (カーソル位置を保存)」を含めます。

tput cup 23 45

カーソル位置を保存したら、カーソル座標を 23,45 に移動します。

echo “Input from tput/echo at 23/45”

情報を stdout に表示します。

tput rc

情報が表示されたら、カーソルは tput sc によって保存された元の位置に戻らなければなりません。カーソルが最後に保存された位置にカーソルを戻すためには、rc オプション、つまり「restore cursor position (カーソル位置を復元)」を含めます。

注意: この記事では最初にコマンドラインでの tput の実行を細かく説明しているため、毎回プロンプトを表示してから各コマンドを別々に実行するよりも、皆さん自身のサブシェルの中でコマンド群を実行した方がわかりやすいはずです。

カーソルの属性を変更する

機器にデータを表示する場合、カーソルを表示したくないことがあります。カーソルを非表示にすると、データをスクロールする際に画面がすっきりします。カーソルを非表示にするためには civis オプション (例えば tput civis など) を使います。データが完全に表示されたら、cnorm オプションを使って再度カーソルを表示することができます。

テキストの属性

テキストの表示方法を変更することで、メニューの中の一連の単語に注目させたり、あるいは何か重要なことをユーザーに警告したりすることができます。テキストの属性を変更する方法には、テキストを太字にする、テキストに下線を付ける、背景色や前面色を変更する、またカラー・スキームを反転させる、などがあります。

テキストの色を変更するためには、setb オプションを背景色の設定に、setf オプションを前面色の設定に使い、また terminfo データベースの中で割り当てられた色の番号を使います。下記は通常割り当てられていれる数字と色ですが、これは各 UNIX システムによって異なるかもしれません。

  • 0: 黒 (Black)
  • 1: 青 (Blue)
  • 2: 緑 (Green)
  • 3: シアン (Cyan)
  • 4: 赤 (Red)
  • 5: マゼンダ (Magenta)
  • 6: 黄 (Yellow)
  • 7: 白 (White)

次のサンプル・コマンドを実行すると、背景色が黄色に、前面色が赤色に変わります。

tput setb 6
tput setf 4

現在のカラー・スキームを反転するためには、単に tput rev を実行します。

場合によると、テキストに色を付けるだけでは不十分なことや、あるいは別の方法でユーザーの注意を引きたいことがあります。そのための方法として、テキストを太字にする方法、そして下線を付ける方法が 2 つあります。

テキストを太字にするためには bold オプションを使います。下線を開始するためには smul オプションを使います。テキストに下線を付けて表示するのを終了する場合には rmul オプションを使います。


シェル・スクリプトのレベルを高める

これでコマンドラインから tput を使うための基本は理解できたので、他のいくつかの機能と共に、これまでに学んだことをシェル・スクリプトの中で行うことに焦点を当てましょう。まず、tput の他の機能として、機器の種類や行や列の数といった端末情報を抽出する機能や、また画面上のデータをクリアーする機能があります。

対象機器で現在使用できる列の数や幅を判断するためには cols オプションを使います。行数や、行の現在の高さを知るためには、lines オプションを使います。

データをクリアーするためには、どのような結果が必要かによって、いくつかの方法があります。現在のカーソル位置から行の終わりまでのデータをクリアーするためには tput el を使います。現在のカーソル位置からその機器の最後までデータをクリアーするためには tput ed を使います。機器全体をクリアーしたい場合には tput clear を使います。

スクリプトの中にすべてをまとめる

以下のコードは基本的なメニューを作成します。このスクリプトは、この記事で説明した tput の多くのオプションを使用してコーディングを改善するための方法を示しています。

 #!/bin/bash
trap 'get_window_size' WINCH                    # trap when a user has resized the window

_UNDERLINE_ON='tput smul'                       # turn on underline
_UNDERLINE_OFF='tput rmul'                      # turn off underline

get_window_size() {
  _WINDOW_X='tput lines'
  _WINDOW_Y='tput cols'

  _FULL_SPACES='echo ""|awk '
  {
    _SPACES = '${_WINDOW_Y}'
    while (_SPACES-- > 0) printf (" ")
  }''
  _FULL_UNDERLINE='echo "${_UNDERLINE_ON}${_FULL_SPACES}${_UNDERLINE_OFF}"'

  unset _FULL_SPACES
  show_menu

  return 0
}

set_color() {
  tput clear
  PS3="Enter Selection[1-9]:"
  select _COLOR in "Black" "Blue" "Green" "Cyan" "Red" "Magenta" "Yellow" "White" "Exit"
  do
    case ${REPLY} in
       [1-8])  _X='expr ${REPLY} - 1';;
           9)  break;;
           *)  echo "Invalid Color"; continue;;
    esac

    if [[ ${1} = "b" ]]
    then
      tput setb ${_X}
    else
      tput setf ${_X}
    fi
  done
}

show_menu() {
  while [[ -z ${_ANS} ]]
  do
    tput civis
    tput clear

        cat <<- EOF
                Window Size: ${_WINDOW_X} / ${_WINDOW_Y}

                Select => ${_UNDERLINE_ON}     ${_UNDERLINE_OFF}

                ${_FULL_UNDERLINE}
                B) Background Text Color
                F) Foreground Text Color

                X) Exit
        EOF

    tput rc
    tput smul
    tput cnorm

    read _ANS
    tput rmul

    case ${_ANS} in
      [Bb])  set_color "b";;
      [Ff])  set_color "f";;
      [Xx])  tput clear; exit;;
         *)
             echo -e "Invalid Selection: ${_ANS}\c"
             sleep 2
             ;;
    esac
    unset _ANS
  done
}

tput sgr0
tput civis
tput clear
tput cup 3 10
tput sc
tput cup 0 0

[[ -n ${_ANS} ]] && unset _ANS
get_window_size

exit 0

では、このシェル・スクリプトを分解してみましょう。

まず、このスクリプトをどう解釈するのかを設定します。この場合は Bash シェルとして使われます。WINCH シグナル用のトラップも設定し、またトラップされるシグナルのトリガーとして get_window_size 関数を割り当てます。トラップを設定したら、このスクリプトの後の方で入力が楽になるように、2 つの変数を定義します。

#!/bin/bash
trap 'get_window_size' WINCH                    # trap when a user has resized the window

_UNDERLINE_ON='tput smul'                       # turn on underline
_UNDERLINE_OFF='tput rmul'                      # turn off underline

行と列の数を判断するための、get_widow_size という名前の関数を作成します。また機器の幅全体 (全列) に下線を付ける _FULL_UNDERLINE 変数を定義します。

get_window_size() {
  _WINDOW_X='tput lines'
  _WINDOW_Y='tput cols'

  _FULL_SPACES='echo ""|awk '
  {
    _SPACES = '${_WINDOW_Y}'
    while (_SPACES-- > 0) printf (" ")
  }''
  _FULL_UNDERLINE='echo "${_UNDERLINE_ON}${_FULL_SPACES}${_UNDERLINE_OFF}"'

  unset _FULL_SPACES
  show_menu

  return 0
}

ユーザーがテキストの背景色と前面色をテストできるように、set_color という名前の関数を作成します。

set_color() {
  tput clear
  PS3="Enter Selection[1-9]:"
  select _COLOR in "Black" "Blue" "Green" "Cyan" "Red" "Magenta" "Yellow" "White" "Exit"
  do
    case ${REPLY} in
       [1-8])  _X='expr ${REPLY} - 1';;
           9)  break;;
           *)  echo "Invalid Color"; continue;;
    esac

    if [[ ${1} = "b" ]]
    then
      tput setb ${_X}
    else
      tput setf ${_X}
    fi
  done
}

機器のサイズを表示する show_menu という名前の関数を作成します。またこの関数は、カーソルを非表示にする方法、画面をクリアーする方法、テキストを出力する方法、そして保存されたカーソル位置に戻る方法も示しています。

show_menu() {
  while [[ -z ${_ANS} ]]
  do
    tput civis
    tput clear

        cat <<- EOF
                Window Size: ${_WINDOW_X} / ${_WINDOW_Y}

                Select => ${_UNDERLINE_ON}     ${_UNDERLINE_OFF}

                ${_FULL_UNDERLINE}
                B) Background Text Color
                F) Foreground Text Color

                X) Exit
        EOF

    tput rc
    tput smul
    tput cnorm

    read _ANS
    tput rmul

    case ${_ANS} in
      [Bb])  set_color "b";;
      [Ff])  set_color "f";;
      [Xx])  tput clear; exit;;
         *)
             echo -e "Invalid Selection: ${_ANS}\c"
             sleep 2
             ;;
    esac
    unset _ANS
  done
}

次に、いくつかの基本的なカーソル属性を設定します。まず、すべての属性を sgr0 によってクリアーします。カーソルが非表示になり、画面がクリアーされます。今度は非表示のカーソルが 3,10, に移動し、この位置が保存され、そしてカーソルが 0,0 (最上部左端) に移動します。

tput sgr0
tput civis
tput clear
tput cup 3 10
tput sc
tput cup 0 0

最後に関数 get_window_size を呼び出してウィンドウのサイズを取得し、そして戻るときに関数 show_menu を呼び出します。

[[ -n ${_ANS} ]] && unset _ANS
get_window_size

exit 0

まとめ

UNIX のシェル・スクリプトに tput を導入することで、スクリプトのルック・アンド・フィールを改善することができます。UNIX では、ある 1 つのタスクを実現するための方法は何百もあるので、そのタスクに少し色を追加し、またプロフェッショナルな外観にしてはどうでしょう。tput は簡単に学ぶことができ、またスクリプトに対して非常に効果的です。そして画面の外観をより一層制御できるようになることのメリットはユーザーにも実感できるはずです。この記事は tput を使って行えることをほんの少し紹介したにすぎません。tput を使い、少し手間をかけるだけで、本格的なメニューで構成された素晴らしい外観のシェル・スクリプトを作成することができます。

参考文献

学ぶために

製品や技術を入手するために

  • 皆さんの次期開発プロジェクトを IBM trial software で構築してください。developerWorks から直接ダウンロードすることができます。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=AIX and UNIX, Linux
ArticleID=310373
ArticleTitle=tput を理解する
publish-date=04012008