端末で次のコマンドを実行するとき:
x=1
a=($x)
echo $a #output: 1
echo ($x) #output: -bash: syntax error near unexpected token `$x'
上記の出力が異なる理由は何ですか?また、次の2つの出力が異なるのはなぜですか?
$(echo foo) #output: -bash: foo: command not found
(echo foo) #output: foo
PS:コマンドの置き換えを理解しようとしています:$(command)
答え1
Bash では、配列定義、コマンド置換、コマンドグループ化という 3 つの異なる括弧の使用を混在させます。コマンドの置き換えとコマンドのグループ化は標準構文であり、すべてのPOSIX様sh
シェルがこれをサポートしています。さらに、配列を持つシェルは配列定義構文をサポートします。
配列定義
配列は、次の形式の複合割り当てを使用して割り当てられます。
name=(value1 value2 … )
値が指定された値の単一要素を含む配列を作成しますa=($x)
。名前で配列をエコーすると、配列の最初の要素だけがエコーされます。これは、aが標準出力として印刷される様子です。$x
1
echo $a
1
配列に複数の要素がある場合、または"${arrayname[*]}"
を使用して"${arrayname[@]}"
その要素にアクセスできます。 1つ目はすべての配列要素を1つのパラメータに結合し、2つめは各要素を別々のパラメータとして使用します。
bash
この構文は、同様の方法で配列を使用できる他のシェルにのみ適用されます。
コマンド置換(POSIX)
コマンド置換を使用すると、コマンド出力がコマンド自体を置き換えることができます。コマンド置換は、コマンドが次のように括弧で囲まれている場合に発生します。
$(command)
あなたのコマンドは$(echo foo)
シェル置換を実行し、と解析するので、foo
あなたが入力したものと同じですfoo
。コマンドがfoo
存在しないので、bashはこれについて不平を言うでしょう。
コマンドのグループ化(POSIX)
Bash は、実行するコマンドのリストを 1 つの単位にグループ化する 2 つの方法を提供します。命令をグループ化すると、命令の全リストにリダイレクトを適用できます。たとえば、リスト内のすべてのコマンドの出力を単一のストリームにリダイレクトできます。
( list )
括弧内にコマンドリストを配置すると、サブシェル環境(コマンド実行環境を参照)が生成され、リスト内の各コマンドがサブシェルで実行されます。リストはサブシェルで実行されるため、サブシェルが完了した後に変数の割り当てが無効になります。
コマンドは(echo foo)
サブシェルで実行されるため、エコーされます。これはコマンドの置換とは関係ありません。マニュアルによると、サブシェルの変数割り当ては、サブシェルが完了した後に無効です。単純な1行のテキストを作成したい場合に便利です。たとえば、代わりにecho foo
foo
for l in {1..10}; do mycommand "$l"; done; unset l
書くことができます、
( for l in {1..10}; do mycommand "$l"; done )
サブシェルの別の有用な用途は次のとおりです。
( cd folder; ./mycommand )
変える
cd folder; ./mycommand; cd -
あなたのコマンドはecho ($x)
これら3つのカテゴリのいずれにも属さず、bash
構文エラーが報告されます。
変数を正しく引用してください。
該当する場合(たとえば、文字列に変数値を含める必要がある場合)、変数拡張を引用する必要があることにも言及する価値があります。バラよりいつ二重引用符が必要ですか?もっと学ぶ。
たとえば、以下は上記の特定の構文を呼び出しません。
x=1
a="($x)"
echo "$a"
echo "($x)"
ここで両方の呼び出しecho
が出力されます(1)
。
bash
マンページリンク
https://www.gnu.org/software/bash/manual/html_node/Command-Grouping.html
https://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html
https://www.gnu.org/software/bash/manual/html_node/Arrays.html