當試圖定義輔助函式來構建關聯串列時,出現錯誤,我無法自行解決 (BASH 4.4):
/tmp/foo.sh: 第 18 行:'key':語法錯誤:預期運算元(錯誤標記為“'key'”)
對于 BASH 4.3,我得到了:
/tmp/foo.sh: 第 18 行:鍵:未系結變數
這是測驗用例:
#!/bin/bash
set -u
# add services list
add_list()
{
local list="$1"
eval "declare -a ${list}=(); declare -A ${list}_A=()"
}
# add services to list of services
add_service()
{
local list="$1" def="$2"
local s="${def%%:*}"
eval "${list} =('$def'); ${list}_A['$s']='$def'"
}
add_list TEST
add_service TEST 'key:value'
使用兩個陣列的原因是我想按鍵訪問元素,并且我想保留原始順序(實際上${list} =('$s')就足夠了)。
這是輸出bash -x:
> bash -x /tmp/foo.sh
set -u
add_list TEST
local list=TEST
eval 'declare -a TEST=(); declare -A TEST_A=()'
TEST=()
declare -a TEST
TEST_A=()
declare -A TEST_A
add_service TEST key:value
local list=TEST def=key:value
local s=key
eval 'TEST =('\''key:value'\''); TEST_A['\''key'\'']='\''key:value'\'''
TEST =('key:value')
TEST_A['key']=key:value
/tmp/foo.sh: line 18: 'key': syntax error: operand expected (error token is "'key'")
uj5u.com熱心網友回復:
筆記:
- 跳過討論為什么
eval可能不是最好的方法 - 跳過對使用 namerefs 的替代方法的討論
- 將關注 OP 的當前代碼如何(不)創建所需的陣列和快速修復
在函式中宣告的陣列保持區域范圍,除非陣列也用global 標志宣告;考慮以下:
$ mytest() { typeset -a myarray; typeset -p myarray; echo "##### mytest(): exit"; }
^^
$ unset myarray
$ mytest
declare -a myarray # array exists while inside the function
##### mytest(): exit
$ typeset -p myarray
-bash: typeset: myarray: not found # array no longer exists once outside the function
現在添加-g標志:
$ mytest() { typeset -ag myarray; typeset -p myarray; echo "##### mytest(): exit"; }
^^^
$ unset myarray
$ mytest
declare -a myarray # array exists while inside the function
##### mytest(): exit
$ typeset -p myarray
declare -a myarray # array still exists after leaving function
將-g標志添加到OP 當前函式中的兩個陣列宣告:
add_list()
{
local list="$1"
eval "declare -ag ${list}=(); declare -Ag ${list}_A=()"
# ^^^ ^^^
}
注意:函式定義現在add_service可以保持原樣
運行 OP 的測驗:
$ unset TEST TEST_A
$ add_list TEST
$ add_service TEST 'key:value'
$ typeset -p TEST TEST_A
declare -a TEST=([0]="key:value")
declare -A TEST_A=([key]="key:value" )
至于為什么OP的當前代碼會產生錯誤......
在命令提示符下,我們將模擬add_service操作......
$ unset TEST TEST_A # just to make these variables are undefined before calling add_service ...
$ typeset -p TEST TEST_A # verify variables are not set
-bash: typeset: TEST: not found
-bash: typeset: TEST_A: not found
$ TEST =('key:value') # bash recognizes this as valid array syntax and will automagically create a normal (-a) array named TEST
$ typeset -p TEST
declare -a TEST=([0]="key:value")
$ TEST_A['key']='key:value' # bash recognizes this as the correct syntax for an integer-keyed array but has problems processing the string `key` as an integer so ...
-bash: 'key': syntax error: operand expected (error token is "'key'")
$ TEST_A[key]='key:value' # again, looks like correct syntax but in this case no error ...
$ typeset -p TEST_A
declare -a TEST_A=([0]="key:value")
^^
# in this case bash considers key as a variable (ie, bash treats it as $key)
# but since $key is undefined it defaults to 0 and a normal array (-a) is
# created with index 0
$ TEST_A[xxx]='keyX:valueX'
$ typeset -p TEST_A
declare -a TEST_A=([0]="keyX:valueX") # $xxx is undefined, treated as 0, and we end up overwriting previous 0-indexed entry in array
$ key=9
$ TEST_A[key]='key:value'
$ typeset -p TEST_A
declare -a TEST_A=([0]="keyX:valueX" [9]="key:value") # $key is defined (9) so we get a new array entry with index=9
uj5u.com熱心網友回復:
在函式中使用declare會使變數成為區域變數,因此可能無法通過呼叫自定義函式將區域變數轉換為關聯陣列。
對于一個普通的陣列,這是可能的,檢查這個結果:
#!/bin/bash
make_it_an_array() {
[[ $1 =~ ^[[:alpha:]_][[:alnum:]_]*$ ]] || return 1
eval "$1=()"
}
fun1() {
local arr # arr isn't an array, so what will happen?
make_it_an_array arr
printf '"%s" in %s: %s\n' "$1" "$FUNCNAME" "$(declare -p arr 2> /dev/null)"
}
#############################################################
fun1 arr
printf '"arr" in main: %s\n' "$(declare -p arr 2> /dev/null)"
"arr" in fun1: declare -a arr='()'
"arr" in main:
如果替換eval "$1=()"為declare -ga "$1=()"結果將是:
"arr" in fun1: declare -a arr='()'
"arr" in main: declare -a arr='()'
這意味著父函式中變數的區域作用域已經丟失。
在旁邊:
如果$list僅包含變數的名稱,則可以替換:
eval "declare -a ${list}=(); declare -A ${list}_A=()"
和:
declare -a "$list=()"
declare -A "${list}_A=()"
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/537581.html
標籤:狂欢评估关联数组
上一篇:如何在命令列PostgreSQL查詢中正確轉義字符?
下一篇:GIT初始化和連接到Github
