「Transwiki:Bash Shell Scripting」の版間の差分

ナビゲーションに移動 検索に移動
上のスクリプトは<tt>get_password</tt>という名前のシェル関数を作成しています。これは、ユーザーにパスワードの入力を求め、その結果を指定した変数に保管します。<tt>get_password PASSWORD</tt>を実行するとパスワードは<tt>$PASSWORD</tt>に保存されます。<tt>get_password</tt>の呼び出しが成功した場合(これはその終了値によって決まる)、取得したパスワードを標準出力に出力します(これは現実的な仕様ではありません。ここでは<tt>get_password</tt>の動作を説明することだけが目的です)。
この例のget_password関数はシェル関数でなければ実現できないわけではありませんが、シェル関数を使用した結果、読みやすくなりました。このシェル関数はビルトインコマンドのread(ユーザーの入力行を読み取り、それを1つ以上の変数に保存します)を呼び出します。readには、ほとんどのBashプログラマーにはよく知られていないオプションがあります。(<tt>-r</tt>オプションはバックスラッシュ文字の特別な意味を無効にします。<tt>-p</tt>オプションは指定されたプロンプト(この場合は<tt>Password:</tt>)を行頭に表示して入力を促します。そして、<tt>-s</tt>オプションはこのようなパスワードを表示しないようにします(エコーバック無効)。 -sオプションを指定すると、ユーザーの改行も表示されません。そのため、<tt>echo</tt> コマンドで改行を出力しています。さらに、この関数は条件式<tt>-t 0</tt>を使用して、スクリプトの入力が確実に端末からのものになるようにしています。ファイルからの入力は受け付けませんし、パスワードが必要かどうかわかっていない他のプログラムからの入力も受け付けません。(これには議論の余地があります。スクリプトの機能によっては、一般的に、ソースに関係なく標準入力からパスワードを受け入れる方が良い場合があります。ただし、ソースがスクリプトを念頭に置いて設計されているという前提のもとでです。)このような複雑な一連のコマンドに<tt>get_password</tt>という名前を付けると、プログラマーはその部分が何をするのかを理解しやすくなります。
The function <tt>get_password</tt> doesn't do anything that couldn't be done without a shell function, but the result is much more readable. The function invokes the built-in command <tt>read</tt> (which reads a line of user input and saves it in one or more variables) with several options that most Bash programmers will not be familiar with. (The <tt>-r</tt> option disables a special meaning for the backslash character; the <tt>-p</tt> option causes a specified prompt, in this case <tt>Password:</tt>, to be displayed at the head of the line; and the <tt>-s</tt> option prevents the password from being displayed as the user types it in. Since the <tt>-s</tt> option also prevents the user's newline from being displayed, the <tt>echo</tt> command supplies a newline.) Additionally, the function uses the conditional expression <tt>-t 0</tt> to make sure that the script's input is coming from a terminal (a console), and not from a file or from another program that wouldn't know that a password is being requested. (This last feature is debatable; depending on the general functionality of the script, it may be better to accept a password from standard input regardless of its source, under the assumption that the source was designed with the script in mind.) The overall point is that giving sequence of commands a name — <tt>get_password</tt> — makes it much easier for a programmer to know what it does.
シェル関数内で位置パラメータ(<tt>$1</tt>や<tt>$2</tt>などに加えて <tt>$@</tt>と<tt>$*</tt>と<tt>$#</tt>も)を使用するとそれは、そのシェル関数を含むスクリプトの引数ではなく、そのシェル関数の呼び出し時の引数を参照します。スクリプト自体の引数が必要な場合、<tt>"$@"</tt>などを使って明示的にシェル関数の引数として渡す必要があります。(またシェル関数内での<tt>shift</tt>や<tt>set</tt>はそのシェル関数内の位置パラメータに影響します。スクリプト側の位置パラメータには影響しません。)
Within a shell function, the positional parameters (<tt>$1</tt>, <tt>$2</tt>, and so on, as well as <tt>$@</tt>, <tt>$*</tt>, and <tt>$#</tt>) refer to the arguments that the function was called with, ''not'' the arguments of the script that contains the function. If the latter are needed, then they need to be passed in explicitly to the function, using <tt>"$@"</tt>. (Even then, <tt>shift</tt> and <tt>set</tt> will only affect the positional parameters within the function, not those of the caller.)
A function call returns an exit status, just like a script (or almost any command). To explicitly specify an exit status, use the <tt>return</tt> command, which terminates the function call and returns the specified exit status. (The <tt>exit</tt> command cannot be used for this, because it would terminate the entire script, just as if it were called from outside a function.) If no exit status is specified, either because no argument is given to the <tt>return</tt> command or because the end of the function is reached without having run a <tt>return</tt> command, then the function returns the exit status of the last command that was run.