sh posix の ${1+"$@"} と書く時の目的は?
HIDEO
HIDEO
ATOMRSS
  • コード求むID: 323
  • 登録日時:  2008/08/25 22:46
  • 最終更新日時: 2008/10/07 20:37
  • アクセス数: 795
  • タグ:  sh posix
  • codeなにがしブックマークに追加する 0 users
  • このページを del.icio.us に追加
  • このページをはてなブックマークに追加

こんばんは、

sh で ${1+"$@"} 
どのような目的の時に
このような記述をするのでしょうか?
 
それで、
http://docs.hp.com/ja/B2355-60104-02/sh-posix.1.html

--------------------------------
${parameter:+word}
parameter が設定され、ヌルでなければ、 word を置き換えます。そうでなければ、何も置き換えません。

echo  ${d:-$(pwd)} 

上記の式からコロン (:) を省略すると、シェルは parameter が設定されているかどうかを判別するためにチェックだけします。
-------------------------------

の説明があり
この部分に、相当するのではないかと
思ったのですが、
「チェックだけします」
とは
どのような動作をするのでしょうか?




コメント

  • sion
  • 1:sion
  • 2008/08/26 17:36

${1+"$@"} は結果的に "$@" が展開されると思いますので、コマンドライン引数を参照する目的で使えます。ダブルクォートで囲んだ "$@" の場合は、"$1" "$2" ... "$n" のように展開されます。よく似た "$*" は "$1 $2 ... $n" のように展開されます。


sh では ${式} は、パラメータ展開を意味します。

${パラメータ:+代替値} は、以下のような展開を行います。
  パラメータが存在していない場合 → 空文字列
  パラメータが存在しているが値が空の場合 → 空文字列
  パラメータが存在しており、値が空でない場合 → 代替値

コロンを省略した ${パラメータ+代替値} は、以下のような展開を行います。
  パラメータが存在していない場合 → 空文字列
  パラメータが存在しているが値が空の場合 → 代替値
  パラメータが存在しており、値が空でない場合 → 代替値



参照サイトは日本語訳なのだと思われますが、翻訳が少しおかしいのではないでしょうか?

原文は知りませんが、「上記の式からコロン (:) を省略すると、シェルは parameter が設定されているかどうかだけを判別します。(ヌルかどうかのチェックを行わない)」といった理解で良いと思います。

GJ

  • otn
  • 2:otn
  • 2008/08/28 17:11

古いshだと、引数が0個の時に "$@" が空にならずに、クォートされた空文字列 になっていました。通常は空になって欲しいところです。
${1+"$@"} にすることで、引数0個の時には 空、引数があるときには "$@" になり、上記問題点を解決することが出来ます。

ただ、手元のLinuxのbashで--posixオプションを付けて確認してみましたが、引数0個なら "$@" は空になりますね。

おそらく、古い時代のシェルスクリプトをそのまま引き写したのではないでしょうか。

注:空 と クォートされた空文字列の違いは、別のコマンドの引数として渡したときに違いが出ます。空ならそのコマンドは引数0個ですが、クォートされた空文字列だと引数1個で値が空文字列になります。

  • GoodJob
  • 0

  • sion
  • 3:sion
  • 2008/08/29 12:37

だんだん sh 思い出してきました。
もう少し正確な情報で自己フォローしておきます。

単にコマンドライン引数を参照するだけでなく、受け取った引数を、そっくりそのまま別コマンドに渡す場合などに以下のような書き方をします。

exec external_command ${1+"$@"}
理由は otn さんのおっしゃるとおり、古い sh 環境で引数が0個の場合に "$@" が空文字列に
なってしまうのを回避するために以下のように書きたくないから。
if [ $# -eq 0 ]; then
    exec external_command
else
    exec external_command "$@"
fi
${parameter:+word} の展開結果を、前のコメントでは「空文字列」と表記しましたが、
「空」に訂正します。


sh や bash の man を改めて確認しましたが、コロンがある場合には「unset か null の場合」と「それ以外の場合」で場合わけされますが、コロンを省略した場合には「unset の場合」と「それ以外の場合」で場合分けになると説明されています。

一応、手持ちのいくつかの sh で確認してみましたが、unset 判定になるのは、変数 parameter が存在しない場合(いきなり変数参照を行うケース)で、null 判定になるのは、変数 parameter が空の場合(「parameter=」や「parameter=""」のようなケース)でした。

参考までに、コマンドライン引数が無い場合、$# は で、$@ は unset です。
コマンドライン引数が "" 1つの場合、$# は で、$@ は null です。

最近の sh は、変数 undefined を定義していない場合の "$undefined" は空文字列になりますが、引数が0個の場合の "$@" は空になるよう、例外処理されているみたいですね。

  • GoodJob
  • 0

  • HIDEO
  • 4:HIDEO
  • 2008/09/20 23:59

こんばんは、

下記の部分を
自分でも確かめたいのですが、
どのようなスクリプトを書けばいいでしょうか?

ーーー ここから ーーーーー

sh や bash の man を改めて確認しましたが、コロンがある場合には「unset か null の場合」と「それ以外の場合」で場合わけされますが、コロンを省略した場合には「unset の場合」と「それ以外の場合」で場合分けになると説明されています。

一応、手持ちのいくつかの sh で確認してみましたが、unset 判定になるのは、変数 parameter が存在しない場合(いきなり変数参照を行うケース)で、null 判定になるのは、変数 parameter が空の場合(「parameter=」や「parameter=""」のようなケース)でした。

参考までに、コマンドライン引数が無い場合、$# は で、$@ は unset です。
コマンドライン引数が "" 1つの場合、$# は で、$@ は null です。

最近の sh は、変数 undefined を定義していない場合の "$undefined" は空文字列になりますが、引数が0個の場合の "$@" は空になるよう、例外処理されているみたいですね。

ーーー ここまで ーーー

  • GoodJob
  • 0

  • sion
  • 5:sion
  • 2008/09/25 11:56

何かの振る舞いを確認したり理解したりするという局面は、プログラミングをしていれば
日常茶飯事だと思いますので、このぐらいの確認は自力で解決できるように
したほうが良いでしょう。

今回は、一例として確認のしかた(のヒント)を紹介しておきます。


●man の確認
man の見比べは、実際にいくつかの UNIX で man コマンドを見ただけです。
ログイン可能な Solaris や FreeBSD や RHEL などで、man してください。

------------------------------------------------------------
●「unset」と「null」と「その他」の確認
   ~ ${parameter:+word} と ${parameter+word} の比較 ~

(1) ${parameter:+word} と ${parameter+word} の表示結果を見比べるスクリプトを作成する
(2) parameter 部分にいろいろな状態の変数を指定し、比較する
 例:
  ・未定義の変数名
  ・「変数=」の変数名
  ・「変数=""」の変数名
  ・「変数=値」の変数名
  ・その他気になるケースがあれば…

 ※スクリプトを修正しながら繰り返し確認してもかまいませんし、
  1つのスクリプト中で連続して表示してもかまわないと思います。

------------------------------------------------------------
●"$@" の振る舞いを確認する
(1) コマンド引数の個数($#)を表示するスクリプトを用意する
(2) (1) で作成したスクリプトに、変数を引数として渡して実行するスクリプトを作る
(3) 引数としての変数の渡し方を変え、いろいろ実験する
 例:
  ・$*
  ・$@
  ・"$*"
  ・"$@"
  ・${1+"$@"}
  ・未定義の変数名
  ・「変数=」の変数名
  ・「変数=""」の変数名
  ・「変数=値」の変数名
  ・その他気になるケースがあれば…

 ※スクリプトを修正しながら繰り返し確認してもかまいませんし、
  1つのスクリプト中で連続して表示してもかまわないと思います。

  • GoodJob
  • 0

  • HIDEO
  • 6:HIDEO
  • 2008/10/07 20:37

こんばんは、

いつも
回答いただき
ありがとうございました。

GJGJGJ

前へ 1 次へ

コメントする

[block]から[/block]までの範囲はブロック表示されます。
部分的に目立たせたい時や、引用などにお使いください。

[code]から[/code]までの範囲は等幅表示されます。
ソースコードや設定ファイルの記述などにお使いください。

ゲスト投稿者:ゲスト:

関連ソースコード・ノウハウを登録

PDFLib | A library for processing PDF on the fly プレゼン公開・共有サイト handsOut.jp オープンタイプ株式会社 チーム・マイナス6% - みんなで止めよう温暖化

ブックマークコメント