シェルスクリプトに挑戦しよう(10)「read」コマンドでキーボードからの入力を受け取る:“応用力”をつけるためのLinux再入門(30)
今回は、シェルスクリプトの中でキー入力を受け取る際に使用する「read」コマンドを取り上げます。まず、前回に続いて、文字列のパターンで分岐する「case」を使い、キー入力に応じて処理内容を変える方法を紹介します。後半では、readコマンドのその他のオプションについて解説します。
readコマンドとは?
「read」は、標準入力から受け取った内容を1行単位で変数に入れるコマンドです。「read 変数」でキーボードからの入力を待ち、入力された内容を変数にセットします(※)。
※変数名を省略した場合は、変数「REPLY」にセットされます。
なお、本連載では、bashのビルトインコマンドの「read」を使用しています。
●キー入力によって動作を変える(read)
それでは、前回取り上げた「case文」を例に、引数の代わりに、キーボードからの入力に応じて画面に表示するように内容を変えてみましょう。
#! /bin/bash read str #標準入力(キーボード)から1行受け取って変数strにセット case "$str" in #変数strの内容で分岐 [Yy]|[Yy][Ee][Ss]) echo "YES" echo "OK" ;; [Nn]|[Nn][Oo]) echo "NO" ;; *) echo "undefined";; esac
ここでは「read str」でキーボードからの入力を受け取り、「case "$str" in」で分岐しています。分岐内容は、前回の「showyesno」スクリプトと同じです。実行結果は以下のようになります。
$ chomod +x inputyesno $ ./inputyesno n[Enter] ← nと入力して[Enter] NO ← 「NO」が表示された
●メッセージを表示してキーボードからの入力を待つ
readコマンドで入力を受け取って処理を続ける場合、「キーボードからの入力待ち」であることが分かるように、画面にメッセージを表示すると親切です。
例えば、「input? >」と表示して入力を待つならば、「-p」オプションを使って「-p "input? > "」のように指定します。
#! /bin/bash read -p "input? > " str #標準入力(キーボード)から1行受け取って変数strにセット case "$str" in #変数strの内容で分岐 [Yy]|[Yy][Ee][Ss]) echo "YES" echo "OK" ;; [Nn]|[Nn][Oo]) echo "NO" ;; *) echo "undefined";; esac
$ chomod +x inputyesno $ ./inputyesno input? > n[Enter] ← 「input? > 」と表示されたので「n」と入力して[Enter] NO ← #「NO」が表示された
●1文字だけ受け取って次の処理に進む
1文字だけ受け取ったら、すぐ次の処理に進みたい場合は「-n 1」のように文字数を指定します。
この場合、キーボードからの入力では改行しないので、case文の中でメッセージを出力する前に改行するため「echo」のみの行を追加しました。
#! /bin/bash read -n 1 -p "input? > " str #標準入力(キーボード)から1文字け取って変数strにセット echo #空行を出力(キーボードからの入力と次の出力の間に改行を入れるため) case "$str" in #変数strの内容で分岐 [Yy]) echo "YES" echo "OK" ;; [Nn]) echo "NO" ;; *) echo "undefined";; esac
$ ./inputyesno input? > n NO
readコマンドで複数の単語を受け取る
readコマンドでは、空白またはタブで区切った複数の単語(文字列)を受け取ることもできます(※)。
※区切り文字は環境変数「IFS」で変更可能。
例えば、3つの単語を受け取りたい場合は、「read w1 w2 w3」のように変数を3つ用意します。
#! /bin/bash read -p "input 3 words > " w1 w2 w3 echo $w1 echo $w2 echo $w3
以下の実行結果では、空白区切りで3つの単語を入力して[Enter]キーを押しています。
$ ./input3 input 3 words > one two three one two three
指定した変数の個数(今回の場合は3つ)より多く入力した場合は、最後の変数にまとめてセットされます。
$ ./input3 input 3 words > one two three four one two three four #3つ目以降が変数「w3」にまとめてセットされている
逆に、指定した変数の個数より少なく入力した場合、後の変数は空白になります。
$ ./input3 input 3 words > one two one two #「w3」には何も入っていないので空行
●入力を配列で受け取る
入力される単語数が分からない場合は、「配列」を使います。
配列は、1つの名前の変数で複数の値を管理できるようにしたものです。bashの場合は「変数名[1]」のように、数字によるインデックス(添え字)を使って個々の値を参照します。
例えば、「ary」という配列に入力した内容をセットしたい場合は、「read -a ary」のように指定します。入力された内容は、ary[0]、ary[1]、ary[2]……のように、「0」から順番に参照できます。また、配列にセットされた値の個数(要素数)は、「#ary[*]」または「#ary[@]」で調べることができます。
なお、echoコマンドなどで、「$」記号を使って個々の値を参照する際は、「${ary[0]}」のように、変数名全体を{}で囲む必要があります。
以下のスクリプトでは、キーボードから入力された内容を「ary」という名前の配列に格納しています。入力後は、まず、aryにセットした単語の個数を、続いて1つ目の単語を表示しています。
最後の「for 〜 do 〜 done」のブロックでは、aryにセットされた単語を1つずつ表示しています。for文についてはこの後の連載で取り上げます。
#! /bin/bash read -p "input words > " -a ary echo ${#ary[*]} #aryにセットした単語の個数を表示 echo ${ary[0]} #1つ目の単語を表示 echo #空行を表示 for a in ${ary[@]}; do echo $a done
input words > one two three four ← 「one two three four」と入力して[Enter] 4 ← 単語数は4つ one ← 1つ目の単語は「one」 one two three four
readコマンドのその他のオプション
readコマンドには、その他にもファイルから読み込んだり、区切り文字を変えたりするためのオプションがあります。
オプション | 内容 |
---|---|
-p 文字列 | 読み込み前に文字列を表示する(本文参照) |
-d 区切り文字 | 読み込みの区切りとなる文字を指定する(デフォルトは改行) |
-s | 読み込んだ文字をエコーバックしない(入力内容が画面に表示されなくなる) |
-n 文字数 | 指定した文字数分の入力を受け取ったら次の処理へ進む。指定した文字数より前に区切り文字(改行)が入力された場合も次へ進む |
-N 文字数 | 指定した文字数分の入力を必ず受け取ってから次の処理へ進む。指定した文字数分入力するか、ファイルの終了(EOF)またはタイムアウトが発生するまでは終了しない。途中の区切り文字(改行)は無視される |
-a 変数名 | 読み込んだ単語を配列にセットする(本文参照) |
-t 秒数 | 入力待ちの時間が指定した秒数を超えるとエラーとして次の処理へ進む |
-u ファイル名 | 標準入力ではファイルから読み込む |
-e | GNU Readlineを使用する([tab]補完などが可能になる) |
-i 文字列 | 初期値となる文字列を指定する。例えば、「-i abc」とすると、abcまで入力済みとして続きの文字列を受け取る(「-e」指定時のみ有効) |
筆者紹介
西村 めぐみ(にしむら めぐみ)
もともとはDOSユーザーで「DOS版UNIX-like tools」を愛用。ソフトハウスに勤務し生産管理のパッケージソフトウェアの開発およびサポート業務を担当、その後ライターになる。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。地方自治体の在宅就業支援事業にてMicrosoft Officeの教材作成およびeラーニング指導を担当。会社などの“PCヘルパー”やピンポイント研修なども行っている。
Copyright © ITmedia, Inc. All Rights Reserved.