- ベストアンサー
Bourne Shell と POSIX について
現在、会社でLinux 上でバッチプログラムを何本か作成しています。 その中で、規約に「シェルはB シェルとし、冒頭には /bin/sh と すること」というようなことが書かれていました。 これは互換性を意識してのことだと解釈し、拡張表現を使用しないことを 意識して書いていました。 具体的には、export VAR=VALUE みたいな書き方はせずに、 VAR=VALUE; export VAR みたいにするとか。 ところが、Solaris を触る機会があって、そのプログラムを 動かしてみると正しく動きませんでした。 その原因は、関数内でローカル変数を宣言するために local を 使っていたのですが、それが Solaris の /usr/bin/sh が 解釈してくれないためでした。 そこで、以下の疑問点が上がってきましたので、 可能な箇所だけでも回答をお願いできたらと思っています。 1. Solaris の /usr/bin/sh は POSIX に準拠しているのでしょうか? 2. 互換性を意識するのであれば local は使用しない方がよいという 結論だと思っています。それでは、local を使用せずにローカル変数を 使用したい場合や再帰処理を行いたい場合はどのような方法を使うのが 一般的なのでしょうか? それとも、拡張機能無しにそのようなことは できないと考えるべきなのでしょうか? 3. そもそも、POSIX でシェルに求められる必要条件とはどのようなこと があるのでしょうか?(どのようなことが規定されているか。 Google検索で見つけられなかったので、原文がWeb 公開されているので あればURL 指定でも・・・)
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
えー、原文でよいということですのでSingle UNIX Specificationを紹介しておきます。 これのShell & Utilities以下にシェルその他の規定があります。
その他の回答 (3)
- notnot
- ベストアンサー率47% (4901/10362)
#2です。さっき投稿してから、スタックの実装を思いつきました。ただし、空白などシェルの特殊記号は値に持たないという前提。位置パラメータを使います。 localで書いた例: foo(){ test $1 = 0 && return local x x=$1 x=`expr $x - 1` foo $x echo $x } foo 10 localを使わず書き直した例: foo(){ test $1 = 0 && return x=$1 x=`expr $x - 1` set $x $stack stack="$*" foo $x set $stack x=$1 shift stack="$*" echo $x } foo 10
お礼
実装例を記述していただいてありがとうございます。 # 空白などシェルの特殊記号は値に持たないという前提 とのことですが、その前提が当てはまらないとなれば さらに複雑化しそうですね。(笑) おまけに、関数の数は共通部分だけで軽く10個以上あり、 互いに呼び出しあっているので、複雑な実装にしてしまうと パフォーマンスが問題になってきそうです。
- notnot
- ベストアンサー率47% (4901/10362)
関数の再帰呼び出しの場合ですよね。 再帰呼び出しを行う関数のローカル変数がどうしても必要と言うことであれば(それ以前に、無くて済む処理方法は無いかの検討が必要でしょうけど)、 関数を独立したシェルスクリプトファイルにして、シェルスクリプトの再帰呼び出しに書き換えるくらいですかね。 あとは、スタックをシェル変数上に作る方法も考えられます。その場合、スタックからの取り出しに、sedとかexprを複数回使うことになるので、シェルスクリプト再帰の方が実用的かと。
お礼
回答ありがとうございます。 いろいろと提案ありがとうございます。 別シェルにするという発想は投稿をした後に 思いつきました。さらに、POSIX に local が 含まれなかった背景を記述した文書も確認できました。 現時点では指摘いただいたように、 関数部分を別シェルに切り出して グローバル変数を export するか、 local が使えないシェルで起動された場合は local が使えるシェルに exec で切り替える ことを考えています。
Solaris で POSIX に準拠している sh は /usr/xpg4/bin/sh になります。 shell のポータビリティについては、GNU Autoconf info マニュアルの "Portable Shell Programming" が参考になると思います。 http://www.gnu.org/software/autoconf/manual/autoconf.html#Portable-Shell
お礼
回答ありがとうございます。 ご指摘いただいていた文書は事前に確認していて、 /usr/xpg4/bin/shが POSIX に準拠していることまでは 確認できていたのですが、/usr/bin/sh が POSIX に 準拠していないという記述までは確認できなかったので、 ここで質問するに至りました。 現時点では関数部分を別シェルに切り出し、 グローバル変数を export するか、 local が使えないシェルで起動された場合は local が使えるシェルに exec で切り替える ことを考えています。
お礼
回答ありがとうございます。 教えていただいた文書確認しました。 POSIX Shell が意外に高機能で驚きました。 具体的には、$( ) $(( )) alias、・・・ ただ、肝心の「local」については 互換性や別シェルにすることで 問題が回避できるなどの理由により、 は定義されなかったようですね。 現時点では関数部分を別シェルに切り出し、 グローバル変数を export するか、 local が使えないシェルで起動された場合は local が使えるシェルに exec で切り替える ことを考えています。