副教授。配列は再宣言されませんか?

副教授。配列は再宣言されませんか?

メニューなどのプログラムがあります。これには次の連想配列がありますconfig

declare -A config=( [h]="?" [c]="?" [x]="?" [l]="?" [t]="?" [n]="?" )

メインループでは、すべての値が設定されている場合にチェックされます。たとえば、次のようになります。

if [ "${config[h]}" == "Y" ] && [ "${config[c]}" == "Y" ] && [ "${config[l]}" == "Y" ] && [ "${config[x]}" == "Y" ] && [ "${config[t]}" == "Y" ] && [ "${config[n]}" == "Y" ];

今私はいつ終わる一度実行すると、配列の設定を解除して再宣言します。

unset config; declare -A config=( [h]="?" [c]="?" [x]="?" [l]="?" [t]="?" [n]="?" )

しかし、配列が正しく再宣言されていないようです。その理由は、私が設定したとき一つ[C]=Yたとえば、if文の値は渡されます。私はステートメントの本文がifいくつかのテキストの色を変更するので、そうなることを確かに知っています。これは、残りのインデックスが実際に「?」に設定されていないためと思われるため、ステートメントはis beifに単純化されます。私はステートメントの本文にエコーするときは間違いなく私は見ることができるだけだから、これを知っています。[ "${config[c]}" == "Y"]true$config[@]if一つ5の代わりに「Y」。配列を正しく再宣言するには?

編集する
関心をお寄せいただきありがとうございます。

  1. 一部のユーザー入力後、値はYに設定されます。この部分についてはかなり自分がいて質問では省略しました。すべて次の形式に従います。

     read ch
            if [ $ch == "Hosts" ]; then
                    while true; do
                            nano listHosts
                            echo -en "Commit this list of Hostnames? [Y|N to re-edit]: "
                            read yn
                            if [ $yn == "Y" ] || [ $yn == "y" ] || [ $yn == "yes" ]; then
                                    break
                            elif [ $yn == "N" ] || [ $yn == "n" ] || [ $yn == "no" ]; then  
                                    continue
                            fi      
                    done
                    config[h]="Y"
    
  2. クサランダさんのコメントについて大小文字が正しいか確認してみましたが、常に小文字「c」ですね。また、そうです。私の言葉は${config[@]}

  3. -p を宣言すると、いくつかの情報が提供されます。 declare -a config='([0]="Y")'

-pが小文字のaを使用したと言うのはなぜですか?呼び出しの順序は次のとおりです。

 unset config
 declare -A config=( [h]="?" [c]="?" [x]="?" [l]="?" [t]="?" [n]="?" )   

readその後、次のように$ ch = "Commands"を設定しました。

 elif [ $ch == "Commands" ]; then  
                while true; do
                        nano iSet
                        echo -en "Commit this list of commands? [Y|N to re-edit]: "             
                        read yn                        
                        if [ $yn == "Y" ] || [ $yn == "y" ] || [ $yn == "yes" ]; then           
                                break
                        elif [ $yn == "N" ] || [ $yn == "n" ] || [ $yn == "no" ]; then                  
                                continue        
                        fi      
                done        
                config[c]="Y"
                declare -p config

Bodoが提​​案したように、より小さなスクリプトで再作成しようとしました。

dec() {
        declare -A config=( [h]="?", [c]="?" )
}
test() {
        declare -p config
        if [ "${config[h]}" == "Y" ] && [ "${config[c]}" == "Y" ]; then 
                echo "Yup"
        fi
}

dec
config[h]="Y"; config[c]="Y"

unset config
dec
config[h]="Y" 

test

他のスクリプトと同様にiftrue と確認されます。 declare -a config='([0]="Y")' Yup

ベストアンサー1

関数では、配列をグローバル配列として宣言する必要がありますdeclare -g ...。それ以外の場合、配列はローカル変数になります。機能上。バラよりhttps://unix.stackexchange.com/a/136721/330217

一部のデバッグ出力とともに、この修正されたスクリプトを参照してください。

#! /bin/bash

# set -x

dec() {
        # declare -A config=( [h]="?", [c]="?" )
        declare -gA config=( [h]="?" [c]="?" )
        echo dec: ${config[*]}
}
test() {
        declare -p config
        if [ "${config[h]}" == "Y" ] && [ "${config[c]}" == "Y" ]; then
                echo "Yup"
        else
                echo "No"
        fi
        echo test: ${config[*]}
}

dec
echo 1: ${config[*]}
config[h]="Y"; config[c]="Y"
echo 2: ${config[*]}

test

unset config
dec
echo 3: ${config[*]}
config[h]="Y"
echo 4: ${config[*]}

test

出力は次のとおりです

$ ./script
dec: ? ?
1: ? ?
2: Y Y
declare -A config=([c]="Y" [h]="Y" )
Yup
test: Y Y
dec: ? ?
3: ? ?
4: ? Y
declare -A config=([c]="?" [h]="Y" )
No
test: ? Y

その行のコメントを外し、変更された行にコメントを付けると、出力は次のようになります。

$ ./script
dec: ? ?,
1:
2: Y
declare -a config=([0]="Y")
Yup
test: Y
dec: ? ?,
3:
4: Y
declare -a config=([0]="Y")
Yup
test: Y

@ilkkachuのコメントからコピーされました:

もちろん、連想配列のローカル宣言が範囲外の後、割り当てはconfig[h]="Y"通常の配列を生成します。ここで、インデックスは算術コンテキストで解釈され、h変数の値は(再帰的に)拡張されますh。ケースを設定した後、ゼロと評価した結果が得られるため、空の文字列がconfig[0]設定されます。そしてset -u適用されないため、エラーメッセージもありません。

declare -a config=([0]="Y")これは元のスクリプトの出力で見ることができます。

おすすめ記事