catコマンドがコマンド環境を使用しないのはなぜですか? [コピー]

catコマンドがコマンド環境を使用しないのはなぜですか? [コピー]

AFAIKは、スクリプトの実行catと同様に、実行時に新しいプロセスをフォークする外部コマンドです。しかし、他の外部コマンドで使用されるコマンド環境を使用したいと sh -c思います。cat

f=test.txt sh -c 'cat "$f"'

ファイルの内容を表示できませんか?

f=test.txt cat $f    


注:何が求められていません someVariable=someValue command。なぜ最初の例ではコマンド変数を使用し、2番目の例では使用しないのかを尋ねます。 2番目の例で変数拡張がどのように行われるかは、最初の例でも発生する必要があります。

ベストアンサー1

一般化する

単一引用符コマンドパラメータを拡張する前にf=test.txt sh -c 'cat "$f"'変数割り当てが発生するため、このコマンドは出力を生成します。一重引用符は、サブコマンドが実行される前に拡張が発生するのを防ぎます。f=test.txt'cat "$f"'cat "$f"

このコマンドf=test.txt cat $fいいえf=test.txt変数の割り当てが発生するため、出力を生成します。後ろに(引用符なし)コマンドパラメータ拡張$f

なぜf=test.txt cat $f出力が生成されないのですか?

f=test.txt cat $fまず、予想通りにこのコマンドが出力を生成しない理由を説明します。ここでは、評価順序について少し混乱があるかもしれません。簡単なコマンド

f=test.txtコマンド本文の変数拡張($fin拡張など)cat $fの前に、コマンドプロローグの変数割り当て(割り当てなど)が発生すると想定できます。しかしそれは真実ではない。これを確認するにはページをご覧ください。簡単なコマンド拡張Bash マニュアルで、または簡単なコマンドのセクション内部にPOSIX仕様。両方の参照には、次の段落が含まれています。

「単純なコマンド」は、任意の順序で任意の変数割り当ておよびリダイレクトのシーケンスであり、任意にワードおよびリダイレクトが続き、制御演算子によって終了される。

与えられた単純なコマンドを実行する必要がある場合(つまり、AND-ORリストまたはケースステートメントは単純なコマンドをバイパスしません。)コマンドテキストの最初から最後まで、次の拡張、割り当て、およびリダイレクトを実行する必要があります。

  1. 次の規則に従って変数の割り当てまたはリダイレクトによって識別される単語シェル構文規則ステップ3と4の処理のために保存します。

  2. 変数の割り当てやリダイレクト以外の単語は拡張する必要があります。拡張後に残りのフィールドがある場合、最初のフィールドはコマンド名として扱われ、残りのフィールドはコマンドの引数です。

  3. リダイレクトは、次の説明に従って実行する必要があります。リダイレクト

  4. チルダ拡張、パラメータ拡張、コマンド置換、算術拡張、および引用符の削除を割り当てる前に、すべての変数割り当てを拡張する必要があります。

手順 2 ではコマンドで変数の拡張が行われますが、手順 1 では変数の割り当てが手順 3 と 4 に保存されることに注意してください。したがって、式は割り当てが発生する前cat $f(引数なし)に拡張されます。これは、出力が出ない理由を説明します。catf=test.txt

このトピックの詳細については、次の投稿をご覧ください。

なぜf=test.txt sh -c 'cat "$f"' する出力を生成する

次に、なぜコマンドが必要なのかを説明します。f=test.txt sh -c 'cat "$f"' する出力を生成します。そのためには私たちは見なければなりません。シェルで実行される一般的なタスクの完全なリスト:

  1. シェルはファイルから入力を読み取ります(参照:シェン)、-cオプション、またはシステム()そしてポップペン()POSIX.1-2008システムインターフェースボリュームで定義されている機能。シェルコマンドファイルの最初の行が「#!」文字で始まる場合、結果は指定されません。

  2. シェルは入力をトークンに分割します。単語と演算子を参照してください。トークン認識

  3. シェルは入力を簡単なコマンドで解析します(参照:簡単なコマンド)と複合コマンド(参照:複合コマンド)。

  4. シェルは、各コマンドのさまざまな部分に対して(別々に)さまざまな拡張を実行して、コマンドと引数として処理されるパス名とフィールドのリストを生成します。単語表現

  5. シェルはリダイレクトを実行します(参照リダイレクト) 引数リストからリダイレクト演算子とそのオペランドを削除します。

  6. シェルは関数を実行します(参照:機能定義コマンド)、内蔵(参照)特別な組み込みユーティリティ)、実行可能ファイル、またはスクリプト(パラメータ名を1からnまでの位置引数として指定し、コマンド名(またはスクリプト内の関数のスクリプト名を指定)を0の位置引数として指定します(参照)。命令の検索と実行)。

  7. シェルはオプションでコマンドが完了するのを待ち、終了ステータスを収集します(参照:コマンドの終了ステータス)。

ここでは、関数/組み込み/実行可能/スクリプト呼び出しを表示できます(このリストのステップ6)。後ろに単純なコマンドを解析します。だからf=test.txt割り当てが発生します今後プログラムの実行sh -c 'cat "$f"'。パラメータは一重引用符で囲まれているため、解析のみが行われます。後ろにコマンドが実行されます。したがって、サブコマンドはcat "test.txt"

おすすめ記事