- ベストアンサー
UNIXシェルプログラミング ${@+"$@"}
「入門UNIXシェルプログラミング」という書籍に以下のような記述がありました。 どうも矛盾しているようで、理解できないのですが、シェルに詳しい方、解説をお願いできないでしょうか。よろしくお願い致します。 以下の文章が、もし「"$@"は""に、"$*"はNULLに置き換わります。」なら理解できるんですが・・・ 誤植では、ないですよね…? (以下引用)-------------------------------------------------------- $*をダブルクウォートで囲むと、1つの文字列になります。$@をダブルクォートで囲むと、それぞれ別々の文字列であると解釈されます。 それならいつでも、「"$@"」を使えば混乱がなくていいじゃないか、と思われるかもしれません。 ところがこれにはこれで落とし穴はあるのです。 位置パラメタに何の値もセットされていない場合、つまり、渡すべきパラメタが何もない状態のときには、"$@"はヌルに、"$*"は""に置き換わります。 ヌルの場合はパラメタとして処理しませんが、""は「何もないパラメタがある」として処理します。どちらを選択しなければならないかは、状況によって判断しなくてはなりません。 一般的には、前節で説明した${variable+value}の形式を使うのが最適でしょう。 ${@+"$@"} こう書くことで、位置パラメタに何もセットされていない場合には何もしない、という条件を作れます。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
この記述は、パラメータ無しの時の "$@" の展開が昔と今では違っていることを踏まえて無いので一部意味不明になってます。 例えば、引数が、a "b c" d という3つの文字列のとき、"$1" は a, "$2" は "b c", "$3" は d になります。 "$@" は、a "b c" d の3つの文字列になり、"$*" は、"a b c d" と1つの文字列になります。引用符で囲まず、単に $@ や $* と書くと、a b c d という4つの文字列になります。 で、引数の個数がゼロのとき、"$*" は "" (空文字列) という1つの文字列、つまり "$*" は引数の個数に関係なく常に1つの文字列になります。これに対して、"$@" は「空」つまりゼロ個の文字列に展開されます。 つまり、シェルスクリプトの引数をできるだけそのまま子供のコマンドに伝えるときには、"$@" を使えばいい訳です。これで、引数の個数がゼロ個であれ、たくさんであれ、引数が引用符で囲まれていても常に、親スクリプトの引数と同じ物、同じ個数が子コマンドに渡ります。 ところが、昔の/bin/shでは、引数がゼロ個の時の "$@" は空でなく "" という1つの空文字列に展開されるという仕様でした。このため、「できるだけそのまま子供のコマンドに伝える」という場合には、${@+"$@"} と書く必要がありました。現在のほとんどのshでは、"$@" でOKです。もしかすると古い仕様のままのshがあるかもしれませんが。
その他の回答 (3)
- bakakyatap
- ベストアンサー率38% (115/299)
>「入門UNIXシェルプログラミング」 最初に見る本としては、間違えましたね。奥付をみて、なるべく最近発行された本を見ましょう。 また、プログラム言語や、フレームワークの本は、同じ種類の本を2、3冊見るようにしましょう。 辞書みたいに、何年もかけて、第一人者が書くというものではないので、表現が微妙であったり、わかりにくかったり、説明不測の所があったり、この辺に突っ込みを入れるあなただと、本意を見失ってしまう事があります。 この本の、ここで言いたいのは、業務用などプログラムするときの心構えを述べています。 つまり、 1. $* などは特殊な意味を持つが、その戻り値(参照値)は必ずしも固定されていません。 と言う話と 2. ユーザーが入力する値だったり、何かを取得して格納する変数は、初期化又は、何が入力されていても、予期しておく。 この2つを言いたかっただけです。NULLであろうがヌルであるがナルであろうが、””長さ0の文字列であろが、たいした問題ではありません。これらのために ========================= ${変数名+初期値または設定値} と言う書式があります。 ===================== と言うのが本文です。これらはオンラインヘルプの man で > man sh > man csh とかすれば、ちゃんと説明されています。ちなみにその本はちょっと硬くて、実用性がないですね。 よものであれば、リファレンスの項目がしっかりしているものを買いましょう。そうすると、上達したあとでも、役に立ちますし、今回の問題もちゃんと説明しています。
お礼
ありがとうございます。 おかげで言語などを学ぶ際の基本的な考え方について気付かされたように思います。 また、上達したあとにも役に立つ書籍や考え方についても参考にさせて頂きたいと思います。
- notnot
- ベストアンサー率47% (4900/10360)
#2です。 まさのその理解でいいと思います。 パッケージの一部として商用Unixを含めて見知らぬ他人に広く使ってもらうなら、${@+"$@"} のほうがいいかもと言うくらいですかね。Linuxだと/bin/shはまず間違いなくbashなので心配ないですが。FreeBSDも大丈夫ですね。 なお、たまに、for i in "$@" とか for i in ${@+"$@"} というのを見かけるのですが、これは、for i と、in部を省略するのがよいです。
お礼
丁寧にお答え頂き本当にありがとうございます。 おかげで、理解する事ができました。
- kmee
- ベストアンサー率55% (1857/3366)
"$@"は $1があれば"$1", $2があれば"$2", $3があれば"$3" .... と展開します。なので、展開できるものが無ければヌル(空)です。 "$*"は $*を展開→全体を文字列 とするものです。 他の変数を使ったもの、例えば "$i" としたのと同じです。このとき、iが空なら""(長さ0の文字列)となります。
お礼
ご解答有難うございます。 たしかにその部分は理解できたのですが、 >${@+"$@"} >こう書くことで、位置パラメタに何もセットされていない場合には何もし >ない、という条件を作れます。 の部分がどうも納得いかないのです。
お礼
ご回答ありがとうございます。 つまり、基本的に "$@" はNULLと解釈されるが、一部のshによっては、""と解釈される場合もあるので、「汎用性」という意味で(念のため)${@+"$@"} と書いておくのが良いという事でしょうか? この解説が、抜けている上に、"$@"と"$*"の説明に続けて説明しているので混乱を招いているという事で理解すれば良いのでしょうか…。