質問: '' ]; then echo success ;fi $ echo $test_var // 何も表示されない ``` 関数側で$1をechoしてみましたが引数自体が渡されていないようでした。 if文内に引数付きの関数を正常に実行する方法など教えていただけますと幸いです・・・ よろしくお願いいたしますmm
回答: シェルで$varなどとして参照できる変数には2種類の意味合いの物があります。 * 環境変数以外の変数 シェルが内部的に管理する変数です。同一のシェルプロセスの中でのみ参照・設定ができますが親プロセスや子供プロセスの変数の参照・設定はできません。 * 環境変数 unix系OSの仕様で「親プロセスから子供プロセスへ引き継ぐことを目的にプロセスのメモリー空間内に保存された名前,値の組の情報」として決まっているものです。これはプロセスイメージ(メモリーの中身)が決まるとき、親プロセスの内容が引き継がれます(execvpeシステムコールを使うと引き継がずに異なる環境変数を明示できますが)。 bashでは環境変数でない変数を環境変数に昇格(?)することがexportにより行えます。しかしexportといっても子供プロセスへ引き継げるだけであって親プロセスへは反映できません。 要するに上の二つの変数のいずれも**子供プロセスから親プロセスの変数の書き換え**はできません。 testはビルトインコマンドなので子供プロセスではなく現在のシェルプロセス内で実行されます。ただしtestには**引数を評価する能力はない**ので、関数呼び出しをtestの引数部分に直接書きたいならバッククォート構文を使うしか手がありませんが、他の方の回答にあるようにバッククォート構文は子プロセスで実行されるため関数は実行できても関数内で行った変数の変更は意味を失います。 このようにシェル上で使えるコマンドや構文には子供プロセスを生成してそこで実行されるものと子供プロセスを生成せずに元のシェルプロセス内で実行されるものがあります。前者には変数の参照・設定, 関数の定義・呼び出し, test/cd/if/case/forなどのビルトインコマンド, { ... }などがありますし、後者はビルトインコマンド以外のコマンド, バッククォート構文, ( ... )などがあります。シェルスクリプトを記述する際にはそれらの違いをきちんと把握しておくと混乱を避けることができると思います。 > > if文内に引数付きの関数を正常に実行する方法 > > > ifと関数呼び出しを組み合わせて使うには 1. ifより以前に関数を呼び出す if文内での実行にはなりませんので解にはなりませんね 2. シェルのバッククォート構文などでtestを起動する前に引数置換をさせる ifに限らず任意の場所で使えるわけですが子供プロセスで実行されるため関数から呼び出し元へ返すことのできる情報はプロセスのリターンステータス、標準出力に限定されます。 3. testを使わずifに続けて直接呼び出す ifはtestと組み合わせることが多いですが任意のコマンドや関数も使えます。その一方でtestが提供する条件式は使えなくなります。子供プロセスでは実行されないため、関数が呼び出し元へ戻せる情報は「変数更新・入出力などの副作用、関数のリターンステータス」になりますがリターンステータスをif文の分岐条件として使うことになります。リターンステータスは「子供プロセスで実行されない」ため、exitではなくreturnで返すことに注意します。exitとするとif文の条件判定の途中でシェルプロセスが終了してしまいますw; ``` function test_func() { RTN="$1$1" case $1 in case a) return 0;; case *) return 1;; esac } if test_func a; then echo "true and RTN=$RTN" fi ==> 実行すると... true and RTN=aa ``` しかし関数が「何かの判定をする」機能と「変数を更新する」機能をごっちゃに持ってしまうためなんとなくパラノイアぎみのスクリプトに見えます。とはいえ、シェルスクリプトは手早く短くやりたいことができればいいと考えることも多いので「きれいかどうか」は二の次と言えるかもしれませんね。 補足:蛇足とは思いますが・・・ 自分の回答に書いた「子プロセス」とか、他のみなさんが使っておられる言葉「別のシェル」「forkされて実行される」あるいはman bashで使われている「サブシェル」は同様の意味合いです。プロセスはそれぞれが独立したメモリー空間になるのでメモリー空間上に存在するシェル変数等もまたそれぞれ独立して存在しているという点がポイントと思います。