Shebangを使用して--re-interval
で gawk スクリプトを実行したいと思います。 「ナイーブ」アプローチ
#!/usr/bin/gawk --re-interval -f
... awk script goes here
gawkは最初の引数"--re-interval -f"
(空白の周りで分割されていない)で呼び出されるため、動作しません。これは理解できません。そのための回避策はありますか?
もちろん、直接gawkを呼び出すのではなく、最初の引数を分割するシェルスクリプトにラップするか、gawkを呼び出してスクリプトを別のファイルに入れるシェルスクリプトを作成することはできませんが、どうすればよいか疑問に思いましたこれは1つのファイル内にあります。
シバン行の動作はシステムによって異なります-少なくとも Cygwin では、引数を空白で分割しません。私はそのように振る舞うシステムでそれをどうやってやるのか気にしています。スクリプトは移植可能であることを意図していません。
これは(g)awkでうまくいくようです。
#!/bin/sh
arbitrary_long_name==0 "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"
# The real awk program starts here
{ print $0 }
#!
が/bin/sh
を実行することに注意してください。したがって、このスクリプトは最初にシェルスクリプトとして解釈されます。
最初は"exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"
を試しましたが、awkはそれをコマンドとして扱い、入力のすべての行を無条件に出力しました。それが私がarbitrary_long_name==0
を入れた理由です-常に失敗するはずです。あなたはいくつかの意味不明な文字列に置き換えることができます。基本的に、シェルスクリプトに悪影響を与えないawkの偽条件を探していました。
シェルスクリプトでは、arbitrary_long_name==0
はarbitrary_long_name
という変数を定義し、=0
と等しく設定します。
Shebangラインは、POSIX、SUS、LSBまたはその他の仕様の一部として指定されたことはありません。知る限りでは、適切に文書化されていません。
それが何をするかについて大まかなコンセンサスがあります:!
と\n
とexec
itの間のすべてを取る。仮定は、!
と\n
の間のすべてがインタープリターへの完全な絶対パスであるということです。空白が含まれている場合に何が起こるかについてのコンセンサスはありません。
ありがたいことに、1と4は消滅したように見えますが、3はかなり普及しているため、複数の引数を渡すことができることに頼ることはできません。
また、コマンドの場所もPOSIXまたはSUSで指定されていないため、通常、実行可能ファイルのnameをenv
に渡すことにより、その単一の引数を使い果たし、it =実行可能ファイルの場所を特定できます。例えば。:
#!/usr/bin/env gawk
[明らかに、このstillはenv
の特定のパスを想定していますが、/bin
にあるシステムは非常に少ないため、これは一般に安全です。 env
の場所は、gawk
の場所よりもはるかに標準化されているか、さらに悪いことにpython
やRuby
またはspidermonkey
のようなものです。 ]
つまり、実際にはany引数すべてを使用することはできません。
同じ問題に出くわしましたが、シバンでの空白の処理方法(少なくともLinuxでは)のため、明確な解決策はありませんでした。
ただし、short optionsであり、かつconcatenated(GNU way )。
たとえば、あなたが持つことはできません
#!/usr/bin/foo -i -f
しかし、あなたは持つことができます
#!/usr/bin/foo -if
明らかに、これはオプションに短い同等物があり、引数を取らない場合にのみ機能します。
CygwinとLinuxでは、シバンのパスの後のすべてが1つの引数としてプログラムに解析されます。
Shebang内で別のawk
スクリプトを使用して、これを回避することができます。
_#!/usr/bin/gawk {system("/usr/bin/gawk --re-interval -f " FILENAME); exit}
_
これにより、awkで{system("/usr/bin/gawk --re-interval -f " FILENAME); exit}
が実行されます。
そして、これはシステムのシェルで_/usr/bin/gawk --re-interval -f path/to/your/script.awk
_を実行します。
厳密には移植性はありませんが、coreutils 8.30および そのドキュメントによる から開始して、以下を使用できます。
#!/usr/bin/env -S command arg1 arg2 ...
与えられた:
$ cat test.sh
#!/usr/bin/env -S showargs here 'is another' long arg -e "this and that " too
あなたが取得します:
% ./test.sh
$0 is '/usr/local/bin/showargs'
$1 is 'here'
$2 is 'is another'
$3 is 'long'
$4 is 'arg'
$5 is '-e'
$6 is 'this and that '
$7 is 'too'
$8 is './test.sh'
興味がある場合は、showargs
は次のとおりです。
#!/usr/bin/env sh
echo "\$0 is '$0'"
i=1
for arg in "$@"; do
echo "\$$i is '$arg'"
i=$((i+1))
done
元の答え ここ 。
#!/bin/sh
''':'
exec YourProg -some_options "$0" "$@"
'''
上記のシェルシバントリックは、/usr/bin/env
。
Gawkマニュアル(http://www.gnu.org/manual/gawk/gawk.html)では、セクション1.14の最後に、Shbangラインからgawkを実行するときに単一の引数のみを使用する必要があることに注意してください。 OSはgawkへのパスの後のすべてを単一の引数として扱うと言っています。おそらく--re-interval
オプションを指定する別の方法がありますか?おそらく、スクリプトはShebang行でシェルを参照し、gawk
をコマンドとして実行し、スクリプトのテキストを "here document"として含めることができます。
なぜbash
とgawk
自体を使用して、過去のShebangをスキップし、スクリプトを読み、それをファイルとしてgawk [--with-whatever-number-of-params-you-need]
の2番目のインスタンスに渡すのですか?
#!/bin/bash
gawk --re-interval -f <(gawk 'NR>3' $0 )
exit
{
print "Program body goes here"
print $1
}
(-sed
やtail
などでも同様に実現できますが、bash
とgawk
自体のみに依存する美しさがあると思います;)
楽しみのために:ファイル記述子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行目で行われているように)を引用する必要があるためです。