
是否在 bash 中declare -a A
建立一個空數組A
,或只是設定一個屬性以防A
稍後分配?
考慮這段程式碼:
set -u
declare -a A
echo ${#A[*]}
echo ${A[*]}
A=()
echo ${#A[*]}
echo ${A[*]}
A=(1 2)
echo ${#A[*]}
echo ${A[*]}
預期輸出應該是多少?
在 Bash 4.3.48(1) 中,我bash: A: unbound variable
在查詢 後的元素數量時得到declare
。訪問所有元素時我也會遇到該錯誤。我知道 Bash 的更高版本對此有不同的處理方式。我還是想知道是否declare
真的定義一個變數(為空)。
答案1
這取決於對應的變數是否已經在目前作用域(頂級也稱為全域或目前函數)中聲明過。
如果尚未在目前作用域中聲明它(請注意,在頂級作用域中,該變數可能具有宣告(並透過從環境導入它來分配),然後聲明它(在函數作用域中使其成為函數的本地函數),為其分配一個類型,但不初始化它,甚至不初始化為空列表(declare -p a
顯示declare -a a
,不像declare -a a=()
您用 ) 聲明和/或分配它那樣a=()
。
如果它已經在目前作用域中聲明(例如,因為它是在全域作用域中從環境中作為標量變數匯入的),那麼declare -a a
將嘗試轉變它到一個數組。
如果它以前是標量,那麼它就會變成([0]=value-of-the-variable)
數組。如果它已經是一個數組,則保持不變。如果它是關聯數組,則會失敗並出現cannot convert associative to indexed array
錯誤。
請注意,這declare a
不會將數組或散列轉換為標量。bash
無論如何都無法將哈希/數組轉換為標量。您可以使用declare +aA a
強制標量(如果變數以前是目前範圍內的雜湊/數組,則會失敗並出現錯誤)。
在您的情況下,該變數可能尚未在當前作用域中聲明,因此它最終被聲明但未分配,這解釋了為什麼嘗試在set -u
.
兩者之間的區別宣告和分配的/放變數的狀態不特定於bash
。在 POSIX 中sh
,您還可以export
建立變數或readonly
不為其賦值。
$ sh -uc 'unset -v var; readonly var; : "$var"'
sh: 1: var: parameter not set
請注意,unset
取消設定和取消聲明變數。在 中bash
,mksh
它yash
可以從外部範圍恢復變數。
在 中zsh
,除模擬外,如果變數尚未設定或已設定但來自不同類型(標量、陣列或關聯數組),則sh
using on 變數會聲明並將其設為空值。typeset