• ベストアンサー

#!/bin/gawk -f ???スクリプトの一行目

bashのスクリプトの一行目に、環境に合わせて、 #!/bin/gawk -f とか #!/usr/local/bin/bash -f とか書かないとだめですよね。 環境が変わるごとに(bashのパスが変わるごとに)この部分を書き換えるのが面倒なのですが、よい方法はないものでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.5

#!の次の文字列をプログラムと見なして、残りの文字列をそのプログラムへの第一引数として、ファイル名を第二引数としてプログラムを実行するというのはbash等のシェルの機能じゃなくてOSカーネルの機能です。カーネルの機能のため、シェルのような複雑なコマンドライン解析機能は組み込まれていません。 一行目が#!で始まらない実行可能ファイルをシェルから起動した場合、シェルスクリプトとして実行されるのでbashからbashスクリプトを実行するなら1行目からいきなりスクリプトを書けばOKです。ただしシェル以外から起動される場合はエラーになりますが。直接シェルから起動しなくても例えばC言語のsystem()関数はシェル経由でプログラムを起動するのでこういった場合もOKです。 >・env がスペース付き引数に対応する env は元々、env VAR=value cmd arg1 arg2 のようにcmd arg1 arg2 を実行する際に環境変数VARにvalueという値を設定してから実行するというコマンドなのでこういう変更はありえないです。envの改造じゃなくてコマンドラインを解析するミニシェルを作ってそれを #!/bin/minish awk -f のように指定すればOKです。 >・"gawk -f" に対応するコマンド gawkf (?)を用意する(gawk -f を一つの引数にするため) そのgawkfをどこのディレクトリに置くかという問題が新たに発生します。 ちょっとトリッキーで一部制約もありますが、shはまず間違いなく/binにあるので、gawkの場合、 #!/bin/sh ZZ==1{ exec sh -c "cat $@ | gawk -f $0" ;} awkスクリプト 。。。 で、大抵のケースは出来ると思います。上に書いたようにシェルからしか起動しないなら1行目は不要です。 ruby言語だとこういうことを想定してあって、#! ruby という行まで読み飛ばす -x というオプションがあります。この際、rubyに乗り換えては? #!/bin/sh exec ruby -S -x $0 $@ #! ruby rubyスクリプト 。。。

white-tiger
質問者

お礼

> ・・・というのはbash等のシェルの機能じゃなくてOSカーネルの機能です。 そうだったのですね!今まで、呪文のように意味も分からず #! と書いていました。賢くなりました。 > >・env がスペース付き引数に対応する >env は元々、・・・こういう変更はありえないです。 なるほど。すごく納得しました。 この件について質問があるので、新しい質問をたてます。 ありがとうございました!!

その他の回答 (4)

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.4

バグレポートに返事が返ってきました。 #!構文にはひとつのインタプリタ言語しか置けずenv commandがスペースで区切られた構文(gawk -f)を一個のファイルとして認識してしまうのは、バグではなくPOSIXの仕様によるものだとのことです。私のパッチはこれを分離し、コマンド(gawk)と引数(-f)に分離するものでしたが、却下されてしまいました。 仕様ならしかたないですが、便利なものは仕様がどうあれ浸透するものです。あとでほとんどbashの機能をパクッた#! line用スパーインタプリターを作りたいなどとひそかに思っています。 -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- Traditional systems that parse #! lines can only give a single argument to the interpreter being invoked. This is not a feature of env, but of the operating system. That explains why env is getting "awk -f" as a single argument. Unfortunately, POSIX prohibits env from performing whitespace word splitting on its arguments, so while the effort of your patch is appreciated, it probably will not be applied. See the POSIX requirements on env here: http://www.opengroup.org/onlinepubs/009695399/utilities/env.html When using /usr/bin/env as the interpreter in a #! line, you must be sure that there is only one more word on the line, which means that you cannot use env to invoke another program while still providing arguments to that program.

white-tiger
質問者

補足

ありがとうございます! パッチが書けるのですね。。すごい・・・ 方法としては、 ・env がスペース付き引数に対応する もしくは ・"gawk -f" に対応するコマンド gawkf (?)を用意する(gawk -f を一つの引数にするため) といった感じでしょうか・・

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.3

>#!/usr/bin/env gawk -f >とやってみたのですが、 >/usr/bin/env: gawk -f: No such file or directory >と怒られます。なぜでしょうか・・ envのバグのようです。 ソースを取ってきてパッチしたら、動くようになりました。さーてと、バグレポートを書こうかな。

回答No.2

#!/usr/bin/env bash で、どうでしょうか? (すべての環境でOKとは言い切れませんが、 たいていの場合、これで良いとおもいます。)

white-tiger
質問者

お礼

すみません。調子に乗って gawk のスクリプトについても #!/usr/bin/env gawk -f とやってみたのですが、 /usr/bin/env: gawk -f: No such file or directory と怒られます。なぜでしょうか・・

white-tiger
質問者

補足

ありがとうございます! これは目から鱗な情報ですね。 env bash というのはどういう意味なのでしょうか?

回答No.1

UNIXやLinuxはそういう仕組みになっているので仕方ありません。 Tcl/Tkの場合も、 #!/bin/sh # The next line restarts using wish \ exec wish "$0" "$@" と書かなくちゃならないのですが、Windowsで動作させる場合はこの三行は不要なんですね。

関連するQ&A