
次のコマンドと同様に、
if true; then
IFS=":" read a b c d e f <<< "$test"
本は、割り当てコマンド(IFS ":"
)がメインコマンド()の前に使用される場合、read a b c d e f <<< "$value"
その値が一時的にメインコマンドに有効であることを示しています。したがって、read
コマンドは区切り文字を使用します:
。
しかし、このコマンドのように
if true; then
HOME="hello" echo "$HOME"
エコメッセージはhelloではありません。上記のコマンドは実際に何を意味しますか?
答え1
評価がどのように行われるかという問題で帰結します。どちらの例も同じ方法で動作しますが、シェル(ここではbash)が変数を拡張する方法が原因で問題が発生します。
このコマンドを書くとき:
HOME="foo" echo $HOME
$HOME
拡張コマンドが実行される前。したがって、コマンドに設定した新しい値ではなく元の値に展開されます。変数はHOME
コマンドが実行される環境で変更されますが、親変数から変数を印刷します。echo
$HOME
これを説明するために、次の状況を考慮してください。
$ HOME="foo" bash -c 'echo $HOME'
foo
$ echo $HOME
/home/terdon
上記のように、最初のコマンドは一時的に変更された値を印刷し、2番目のコマンドは元の値を印刷し、変数が一時的にのみ変更さHOME
れたことを示します。コマンドは二重引用符()ではなく一重引用符()で囲まれているため、bash -c ...
変数は拡張されずに変更されずに新しいbashプロセスに渡されます。その後、この新しいプロセスはそれを展開し、設定された新しい値を印刷します。次のコマンドを使用すると、これが起こっていることがわかります。' '
" "
set -x
$ set -x
$ HOME="hello" echo "$HOME"
+ HOME=hello
+ echo /home/terdon
/home/terdon
上からわかるように、変える $HOME
に渡されませんecho
。拡張子の値のみを表示できます。比較:
$ HOME="hello" bash -c 'echo $HOME'
+ HOME=hello
+ bash -c 'echo $HOME'
hello
ここでは、一重引用符のため、変数はその値の代わりに新しいプロセスに渡されます。
答え2
シェルが行を解析すると、その行が単語として表示されます。さまざまな拡張機能の実行(順番に)単語を入力してコマンドを実行します。
考えるtest=1:2:3:4:5:6
このコマンドを見てみましょう。 IFS=":" read a b c d e f <<< "$test"
トークン化後、パラメータ拡張起こる:IFS=":"
read
a
b
c
d
e
f
<<<
"1:2:3:4:5:6"
シェルは読み取りコマンド中にIFS変数を設定し、read
$IFSを入力に適用する方法を学びます。をクリックし、変数名に値を割り当てます。
このコマンドは同様の内容を持っていますが、結果は異なります。HOME="hello" echo "$HOME"
パラメータ拡張が発生したため今後コマンドの先頭には、シェルには次のものが含まれます。
HOME="hello" echo "/home/username"
これにより、echoコマンドの実行中に$ HOMEの新しい値はまったく使用されません。
やりたいことを達成するには、次のいずれかを選択してください。
# Delay expansion of the variable until its new value is set
HOME="hello" eval 'echo "$HOME"'
または
# Using a subshell, so the altered env variable does not affect the parent.
# The semicolon means that the variable assignment will occur before
# the variable expansion
(HOME="hello"; echo "$HOME")
しかし、最初のものを選択しないでください。
答え3
スコープには、環境変数とローカル変数の2つがあります。環境変数はすべてのプロセスに対して有効ですが(参考資料を参照setenv
)getenv
、ローカル変数はそのシェルセッション内でのみ有効です。 (目立つ違いではありません...)
環境変更は、ローカル環境の使用中に暗黙的にenv
(あなたの例のように)行われるため、何の効果もありません。echo ...
env
ローカル変数を変更するには、次のようにします。
( HOME="foo" ; echo "$HOME" )
ここで、括弧は割り当て範囲を定義します。