128

シバンを使ってgawkスクリプトを実行したいです。--re-intervalの「素朴な」アプローチ

#!/usr/bin/gawk --re-interval -f
... awk script goes here

gawk が最初の引数"--re-interval -f"(空白で分割されていない) で呼び出され、これを理解できないため、機能しません。そのための回避策はありますか?

もちろん、直接 gawk を呼び出さずに最初の引数を分割するシェル スクリプトにラップするか、その後に gawk を呼び出すシェル スクリプトを作成し、そのスクリプトを別のファイルに入れることもできますが、何らかの方法があるかどうか疑問に思っていました。これを 1 つのファイルにまとめます。

シバン行の動作はシステムごとに異なります。少なくともCygwinでは、引数を空白で分割しません。そのように動作するシステムでそれを行う方法が気になります。スクリプトは移植性を意図していません。

4

10 に答える 10

162

シバンラインは、POSIX、SUS、LSB、またはその他の仕様の一部として指定されたことはありません。AFAIK、それは適切に文書化されていません。

それが何をするかについては大まかなコンセンサスがあります:ととの間のすべてを!取り\nますexec!との間のすべて\nがインタプリタへの完全な絶対パスであることが前提です。空白が含まれている場合に何が起こるかについてのコンセンサスはありません。

  1. 一部のオペレーティングシステムは、単に全体をパスとして扱います。結局のところ、ほとんどのオペレーティングシステムでは、パス内で空白またはダッシュが有効です。
  2. 一部のオペレーティングシステムは空白で分割され、最初の部分はインタプリタへのパスとして扱われ、残りは個別の引数として扱われます。
  3. 一部のオペレーティングシステムは最初の空白で分割され、前部をインターペッターへのパスとして扱い、残りを単一の引数として扱います(これはあなたが見ているものです)。
  4. シバンラインをまったくサポートしていないものもあります。

ありがたいことに、1。と4.は消滅したようですが、3。はかなり普及しているため、複数の引数を渡すことができることに頼ることはできません。

また、コマンドの場所もPOSIXまたはSUSで指定されていないため、通常、実行可能ファイルの場所を判別できるように、実行可能ファイルの名前をに渡すことにより、その単一の引数を使い果たします。例えば:env

#!/usr/bin/env gawk

[明らかに、これはまだ特定のパスを想定していますがenv、それが存在するシステムはごくわずかである/binため、これは一般的に安全です。の場所envは、の場所よりもはるかに標準化されているか、またはのgawkようなものよりもさらに悪いです。]pythonrubyspidermonkey

つまり、実際には引数をまったく使用できません。

于 2010-11-29T13:26:53.250 に答える
27

これは(g)awkでうまくいくようです。

#!/bin/sh
arbitrary_long_name==0 "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"


# The real awk program starts here
{ print $0 }

#!runsに注意してください/bin/sh。したがって、このスクリプトは最初にシェル スクリプトとして解釈されます。

最初は単純に を試してみ"exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"ましたが、awk はそれをコマンドとして扱い、入力のすべての行を無条件に出力しました。それが私が入れた理由ですarbitrary_long_name==0-それは常に失敗するはずです。意味不明な文字列に置き換えることができます。基本的に、シェル スクリプトに悪影響を与えない awk の false-condition を探していました。

シェル スクリプトでは、arbitrary_long_name==0は という変数を定義し、arbitrary_long_nameそれを と等しくなるように設定し=0ます。

于 2014-09-26T09:48:27.157 に答える
13

シバンで空白が処理される方法が原因で(少なくともLinuxでは)、明らかな解決策はありませんが、同じ問題に遭遇しました。

ただし、短いオプションであり、連結できる(GNU の方法)限り、シバンで複数のオプションを渡すことができます。

たとえば、

#!/usr/bin/foo -i -f

しかし、あなたは持つことができます

#!/usr/bin/foo -if

明らかに、これはオプションに短い同等物があり、引数を取らない場合にのみ機能します。

于 2011-02-10T11:53:43.580 に答える
11

Cygwin および Linux では、シバンのパスの後のすべてが 1 つの引数としてプログラムに解析されます。

awkシバン内で別のスクリプトを使用して、これを回避することができます。

#!/usr/bin/gawk {system("/usr/bin/gawk --re-interval -f " FILENAME); exit}

これは{system("/usr/bin/gawk --re-interval -f " FILENAME); exit}awk で実行されます。これは、システム シェルで
実行されます。/usr/bin/gawk --re-interval -f path/to/your/script.awk

于 2016-04-12T20:03:10.047 に答える
4
#!/bin/sh
''':'
exec YourProg -some_options "$0" "$@"
'''

上記のシェル シバン トリックは、より移植性があり/usr/bin/envます。

于 2014-01-10T19:11:37.700 に答える
3

gawk のマニュアル (http://www.gnu.org/manual/gawk/gawk.html) では、セクション 1.14 の最後で、シバン行から gawk を実行するときは単一の引数のみを使用する必要があることに注意してください。これは、OS が gawk へのパス以降のすべてを単一の引数として扱うことを示しています。おそらく、オプションを指定する別の方法があり--re-intervalますか? おそらく、スクリプトはシバン行でシェルを参照gawkし、コマンドとして実行し、スクリプトのテキストを「ヒアドキュメント」として含めることができます。

于 2010-11-29T12:59:14.430 に答える
0

ちょっとした楽しみとして、ファイル記述子 3 と 4 を介して stdin とプログラムを再ルーティングする次の非常に奇妙な解決策があります。スクリプト用の一時ファイルを作成することもできます。

#!/bin/bash
exec 3>&0
exec <<-EOF 4>&0
BEGIN {print "HALLO"}
{print \$1}
EOF
gawk --re-interval -f <(cat 0>&4) 0>&3

これに関して厄介なことが 1 つあります。シェルはスクリプト上で変数展開を行うため、(スクリプトの 2 行目で行われているように) すべての $ を引用符で囲む必要があり、おそらくそれ以上のものを引用する必要があります。

于 2013-03-15T13:50:24.213 に答える