for ループの Bash 変数の割り当てが「コマンドが見つかりません」を返します。

for ループの Bash 変数の割り当てが「コマンドが見つかりません」を返します。

Bashでは、以下が欲しい。

  1. ID1、ID2、ID3という3つの変数を作成します。
  2. 変数にはそれぞれ文字列値ID1_VALUE、ID2_VALUE、ID3_VALUEが割り当てられます。

このようにforループを作成しました。

for ID_COUNT in 1 2 3; do
    ID${ID_COUNT}=ID${ID_COUNT}_VALUE;
done;

コードスニペットが実行されると、次の結果が表示されます。

ID1=ID1_VALUE: command not found
ID2=ID2_VALUE: command not found
ID3=ID3_VALUE: command not found

そして、ID1、ID2、ID3の値は設定されません(set | grep ID1何も表示されません)。

何が起こっているのかを詳しく説明できる人はいますか?

答え1

bash使用された変数を評価する前に、変数の割り当てを検出するコマンドラインの解釈に特別な注意を払うようです。デフォルトでは、変数の割り当てでは、名前部分は評価から派生した名前ではなく識別名でなければなりません。しかし、「nameref」という概念があります。ここで変数は変数名を値として持ち、これに対する割り当てはその値の名前を付けた変数に対する割り当てになります。あなたの例では、次のように見えます。

for ID_COUNT in 1 2 3; do
    declare -n X=ID${ID_COUNT}
    X=ID${ID_COUNT}_VALUE;
done;

もちろん、eval呼び出しコンテキストでその引数をコマンドとして評価するコマンドを使用して、同じ効果を得ることができます。使用すると、次のようになります。

for ID_COUNT in 1 2 3; do
    eval ID${ID_COUNT}=ID${ID_COUNT}_VALUE;
done;

前述のように、usingはexport同様の効果を持ち、主な機能である変数を子プロセスにエクスポートする機能も提供します。

答え2

現在と将来のスクリプトに配列を使用する方が良いでしょう。

#!/bin/bash

for i in 1 2 3; do
    id[i]="ID${i}_VALUE"
done

echo 'contents of the array "id":'
printf '\t%s\n' "${id[@]}"

このスクリプトの出力は次のとおりです。

contents of the array "id":
        ID1_VALUE
        ID2_VALUE
        ID3_VALUE

スクリプトのループは次のように置き換えることもできます。

id=( "ID"{1..3}"_VALUE" )

中かっこ拡張を使用して配列を作成します。


コードで何が起こるのかは、変数$ID_COUNTの値が2の場合にID${ID_COUNT}=ID${ID_COUNT}_VALUE;拡張されることです。しかし、コマンドを実行したときに変数がすでに検出されているので、ここで取得した内容は次のようになります。ID2=ID2_VALUEひもそこに等号があります。シェルは、コマンド名のように文字列を実行し続けます。

関連情報