このシェルスクリプトがある場合
str="A tremor in the Force.
The last time I felt it was in the presence of my old master."
cat <<< "$str"
私の理解はコマンドです
cat <<< "$str"
/bin/cat
プログラムを呼び出して引数を渡すようにシェルに指示します$str
。二重引用符は、$str
シェルが変更されていない引数を渡すことを保証します。それではcat
、プログラムから取得した変数が$str
変更されていない場合は、変数の値を知る必要がありますか?私の質問は、シェルが環境で宣言された変数を呼び出す他のシステムプログラムに渡すのですか?
答え1
シェルは、環境で宣言された変数を呼び出す他のシステムプログラムに渡しますか?
はい、しかしその場合ではありませんcat <<< "$str"
。
Unixファミリーオペレーティングシステムでは、ほとんどの新しいプログラムがシステム上execve()
で次の理由で実行されます。
int execve(const char *filename, char *const argv[], char *const envp[]);
シェルはexecv
プログラムの実行に使用されます。デフォルトでは、シェルはenvp
コマンドライン引数が渡される方法と同様に、すべての環境変数を渡しますargv
。概念的にはenvp
文字列の配列であり、各文字列の形式はですNAME=value
。
man 2 execve
全体のプロセスは非常に明確に説明されており、作業例コードが含まれています。
の場合、cat <<<"$str"
シェルはcat
oncat
の標準入力に "$ str"を提供するため、cat
名前付き変数はstr
以前にシェルからエクスポートされた場合(たとえば、呼び出しを介して)を除いては見えませんが、2つの変数が何であるかを知ることができます。方法はありませんexport str
。cat
変数は関連しています。
<<<
「Here String」とシェル拡張です。bash
マニュアルページから:
単語は、中括弧拡張、チルダ拡張、パラメータおよび変数拡張、コマンド置換、算術拡張、および引用符の削除です。パス名の拡張とトークン化は行われません。結果は、標準入力のコマンドに単一の文字列として提供されます。
ここで、String は従来のイディオムに似ています。
echo "$str" | cat
私はそれをお勧めします。実際、両方とも標準入力の末尾に改行文字を追加します。出力が何らかの方法で変更されない限り、どちらの方法も同じだと思いますecho
(文字列の内容によって異なる可能性があるため、より安全なバージョンはそうではprintf '%s' "$str"
ありませんecho
)。
printf '%s' "$str" | cat
あなたの場合は、多くのシェルの1つだけを使用してスクリプトの実行をロックすることなく、最も移植性が高く、汎用性があり、理解しやすいので、これを使用します。 POSIXのマニュアルページをシェルスクリプトのドキュメントとして使用する場合は、学習する必要が少なく、sh
学習した内容はすべてのBourneシェル派生に適用されます。
答え2
シェルによって呼び出されたプログラムはシェル変数を継承しません。環境変数のみを継承します。変数を作成するとexport str
(またはあまり一般的ではない)、変数が環境に割り当てられるのではなく、環境に配置されます。
cat
とにかく環境変数は気にしません。
このコマンドcat <<< "$str"
は引数を渡しませんcat
。cat
引数なしで呼び出されますが、シェルは変数値とstr
改行文字を書き込むパイプに接続されている標準入力を使用します。プロセスは(最後の改行文字)を見cat
ませんでした。二重引用符は、変数値のトークン化とワイルドカードを防ぎます。つまり、値に拡張されます。二重引用符と一重引用符を混同する可能性があります。つまり、最後の改行文字を含む5つの文字列を入力として渡します。$str
A tremor … my old master
$str
"$str"
str
cat <<< '$str'
$str
cat