同じ行に変数を割り当てた後にコマンドを実行する移植性に対処する標準はありますか?
APPLE="cider" echo hi
こういうのがどれほど携帯性がいいのでしょうか?どこで動作し、どこで動作しませんか?
また、私のシェルスクリプトは#!/ bin / shで始まります。
答え1
POSIX準拠のシェルを使用しても大丈夫です。
~からシェルコマンド言語のPOSIX定義:(該当事項は太字で表示)
「簡単な命令」は一連のオプションの変数割り当て任意の順序でリダイレクトし、オプションで制御演算子によって終了される単語とリダイレクトが続きます。
与えられた単純なコマンドを実行する必要がある場合(つまり、単純なコマンドが条件付き構造(AND ORリストやCaseステートメントなど)によってバイパスされない場合)、次の拡張、割り当て、およびリダイレクトは次のように実行する必要があります。コマンドテキストの先頭から最後まで:
変数の割り当てとして認識される単語またはリダイレクトに基づいてシェル構文規則ステップ3と4の処理のために保存します。
変数の割り当てやリダイレクト以外の単語は拡張する必要があります。拡張後に残りのフィールドがある場合、最初のフィールドはコマンド名として扱われ、残りのフィールドはコマンドの引数です。
リダイレクトは、次の説明に従って実行する必要があります。リダイレクト。
チルダ拡張、パラメータ拡張、コマンド置換、算術拡張、および引用符の削除を割り当てる前に、すべての変数割り当てを拡張する必要があります。
前のリストから特別な組み込みユーティリティを処理するために、手順3と4の順序を逆にすることができます。特別な組み込みユーティリティ。
コマンド名の結果がない場合、変数の割り当ては現在の実行環境に影響します。そうでなければ、変数の割り当ては、コマンド実行環境に対してエクスポートする必要があり、現在の実行環境に影響を与えてはなりません。(特殊内蔵を除く)
また、#!/bin/sh
非常に重要です。 ~からPOSIXの定義sh
:
shユーティリティは、コマンドライン文字列、標準入力、または指定されたファイルから読み取られたコマンドを実行するコマンド言語ソルバーです。アプリケーションは以下を保証する必要があります。実行されるコマンドは記述言語で表されます。シェルコマンド言語。
sh
したがって、基本的に上記で紹介した規則に従う必要があると言います。
したがって、POSIX準拠のオペレーティングシステムを使用している限り大丈夫です。
答え2
2番目の質問に対する答えは不完全です(シェルの数は次のとおりです)。信じられない)
% for sh in dash ksh93 mksh rc fish bash zsh csh tcsh jsh; do
printf '%s\n' "$sh: $($sh -c 'var=foo echo hi')"
done
dash: hi
ksh93: hi
mksh: hi
rc: hi
fish: Unknown command “var=foo”. Did you mean “set var foo”? For information on assigning values to variables, see the help section on the set command by typing “help set”
Standard input: var=foo echo hi
^
fish:
bash: hi
zsh: hi
var=foo: Command not found.
csh:
var=foo: Command not found.
tcsh:
jsh: hi
これは、ほとんどの現代のKorn様シェルで動作します。しかし、私はそれが標準だとは思わない。一部の人々は好きになると確信しています。スティーブン・チャジェラスどれくらい一般的なことがわかるでしょう。
答え3
うん、昔からそうでした。sh
The environment for any simple-command may be
augmented by prefixing it with one or more
assignments to parameters. Thus these two lines
are equivalent
TERM=450 cmd args
(export TERM; TERM=450; cmd args)
答え4
与えられた例のコマンドがecho
実行されますが、発生する状況は$APPLE
少し複雑です。
@Patrickの回答からわかるように、シェルがプロセスを呼び出すと、呼び出し前にコマンドラインで宣言されたすべての変数がその環境にエクスポートされるように指定されることがあります。また、これらの変数は、呼び出しプロセスとともに期限切れになるように指定されます。したがって...
unset var; var=val cmd; echo ${var-unset.}
...印刷する必要がありますunset.
しかし、あなたの例に見られるように、概念全体は少し複雑になり、この時点cmd
でいいえ呼び出されたプロセスですが、シェル組み込み、シェル関数、または特別なシェル組み込みユーティリティ。これら 3 つのケースのそれぞれでは、シェルはメモリ内で独自のルーチンを実行し、何も呼び出さない可能性が高くなります。
echo
たとえば、ほぼ確実にシェル組み込みユーティリティ - 私が知っているほとんどのシェルが提供するように - しかしいいえPOSIXの指定特別な内蔵。したがって、これは基本的に外部実行可能ファイルをエミュレートする必要があるシェル関数です。これにより、より明確になります。ここで:
「組み込み」という用語は、シェルがユーティリティを検索せずに直接実行できることを意味します。実装では、すべてのユーティリティを組み込むことを選択できます。ただし、ここで説明する特殊な組み込みユーティリティは、一般的な組み込みユーティリティと同じではありません。
特別な組み込みユーティリティを使用して指定された変数の割り当ては、組み込み完了後も維持されます。これは、一般的な組み込みユーティリティやその他のユーティリティの場合には該当しません。
このセクションの特別な組み込みユーティリティは、POSIX.1-2008システムインタフェースボリュームで定義されているexec機能シリーズを介してアクセスできるように提供する必要はありません。
echo
したがって、コマンドラインで宣言された変数は一緒に消えますecho
が、set
コマンドラインで宣言された変数はまだ存在します。(bash
この規則は基本的に違反されますが)。 aの場合もcmd
同様です。シェル機能:
関数が実行されると構文エラーが発生するはずです。特別な組み込みユーティリティで記述されている変数に属性を割り当てる特別な組み込みユーティリティの先頭の列挙リスト。