私の考えでは源泉(つまり。呼ぶ)すべてのシェルのスクリプト(bash / cshが主なターゲットですが、Fish、zsh、ksh、およびrcも興味深いです)。
私はスクリプトが単一のファイルであることを望みました。つまり、各シェル方言のファイルではありません。
私はこれを行うことができますか?
私は次のことを考えています:
if shell is bash then
# bash code here
else
if shell is csh then
# csh code here
else
if shell is xxxsh then
# xxxsh code here
fi
endif
fi
だから私はこれを行うことができます:
csh% source my_script
bash$ . my_script
問題は - もちろん、if
すべての方言が異なるため、すべてのシェルで動作する構文を使用する必要があるということです。
編集する
シェルを検出することが最初のステップです。実行時にスクリプトからシェルを決定するよかったです。
同様に重要なステップは、他のシェルを混同しないように、シェルの他の部分でコードを参照する方法です。考えてみましょう:<<here_document
bashでは許可されていますが、他のシェルでは違法なすべての組み合わせのすべての文字を他のシェルと混同せずにbashセクションにどのように含めることができますか?回答/リンクされた回答のどれもこれに対処しません。
答え1
すべてのシェルに対してコードスニペットを作成しないでください。ほとんどのシェルで解釈できる移植可能なコードのみを記述する必要があります。あなたは少し見なければなりません。POSIX シェルコマンド言語。これは、シェル(POSIX以降)がコードを解釈する方法の標準です。
多くのシェル(たとえばbash
)をPOSIXシェルのように実行するように設定できます。各シェルには独自の機能と特定のシンボルがあります。移植可能なスクリプトでは完全に使用しないでください。
答え2
cshに似た状況とBourneに似た状況では、次のことができます。
start=:#||:<<"goto end="
echo "(t)csh code here"
if { bindkey >& /dev/null } then
echo tcsh
endif
goto end=
echo Bourne-like code here
if [ -n "$BASH_VERSION" ]; then
echo bash
fi
end=:
説明する:
start=:
では、ラベル宣言csh
と変数の代入として扱われるので、sh
2つの無害な作業です。- では注釈リーダーとみなされますが
start=:#
、では別のタグではないのでそうではありません。したがって、次の内容はコメントアウトされていますが、コメントアウトされませんでした。#
csh
sh
csh
sh
- 変数の割り当ては
sh
正常終了ステータス(割り当てにコマンド置換が含まれていない限り)なので、オペレータの||
コマンド権限では実行されません。 - コマンドは
:<<"goto end="...goto end
実行されませんが、解析され無視されます("goto end"
ここではドキュメント内のさまざまな拡張を防ぐという事実が引用されています)。ただし、注:Bourneシェル(Bourneシェルのみ)では、一時ファイルは引き続き作成されます。 goto end=
したがって、Bourneのようなシェルでは、全体の部分は無視され、間の部分はcsh
。 (Bourneなどのシェルから無害な変数を割り当てる)goto end=
が原因で発生します。csh
end=:
シェルのサポートを増やすほど、難しくなります。fish
特にスクリプト全体の構文はもちろん、実行されない部分までチェックするので難しいです。
また見なさい:
- 実行時にスクリプトからシェルを決定する多言語コードの例。
- リモートユーザーのログインシェルを知らず、SSHを介して任意の単純なコマンドをどのように実行できますか?sh/csh/rc/fish 系列のコード (
parallel
シェル呼び出しについて議論したときに書いたコードです)
答え3
これをやろうとする理由は移植性のためだと思います。上記の答えは手がかりを提供します。 Bourneシェル(sh)が最小の共通分母であり、「すべての場所」(Linux、Solaris、Unix、AIXなど)で使用できると仮定すると、スクリプトの先頭に追加してすべての#!/bin/sh
スクリプトを作成できます。 shの機能のみを使用します。 (私の考えでは、LinuxではbashがBourneシェルの親セットであるため、shはbashのエイリアスですが、関係なく動作し続ける必要があります。)
常に存在すると仮定して少し改善してくださいsh
。しかし、高度なシェルの追加のパフォーマンスと便利さを望むかもしれません。したがって、script.bash、script.zsh、script.ksh、script.cshなど、サポートする各シェルのスクリプトバージョンを作成できます。各スクリプトは独自の shebang 行で始まり、スクリプト内で開始されます。 shファイルを使用すると、次のように言うことができます。
#!/bin/sh
if [[ -e /bin/ksh ]] ; then
./script.ksh
exit
elif [[ -e /bin/csh ]] ; then
./script.csh
exit
fi
など。
追加の提案は、自動ツールツールバーのソースコードを研究することです。 ./configure を実行すると実行されます。 GNUの人々は、スクリプトがすべての環境で実行されるようにするために多くの賢いタスクを実行します。