Bash 以列表为值的关联数组
Bash associative array with list as value
我必须使用 Java 工具的输出,它 returns 一个看起来像 HashMap<String, ArrayList<String>
的地图数据结构。我必须使用 BASH 并尝试将其声明为关联数组,这与地图非常相似。 bash 中关联数组的声明应该在一行中,我尝试按如下方式进行。
ARRAY=(["sem1"]=("first name" "second name") ["sem2"]=("third name") ["sem3]=OTHER_LITS)
但这会产生以下错误:
bash: syntax error near unexpected token `('
我可以逐行定义它,但我想把它放在一行中。我如何在 bash 中仅在一行中定义关联数组?
在 BASH 中没有多维数组支持的情况下,您可以使用这个 word-around 关联数组。关联数组中的每个 key
都是 map-index,array-list-index
:
的字符串连接
# use one line declaration
declare -A array=([sem1,0]="first name" [sem1,1]="second name" [sem2,0]="third name" [sem3,0]="foo bar")
# loop thrpugh the map array
for i in "${!array[@]}"; do echo "$i => ${array[$i]}"; done
sem2,0 => third name
sem1,0 => first name
sem1,1 => second name
sem3,0 => foo bar
顺便说一句,关联数组、字典或映射 - 都属于一种抽象数据类型(我们称之为 字典)。
因此,这是将 array 作为值存储在 Bash 的 dictionary 中的解决方案(4+ 版本) .
请注意,Bash 中的 array 是 space 分隔的字符串列表(因此元素内部没有任何 space,即字符串),所以我们可以写一个引用列表:
"firstname middlename secondname"
作为 X
字典中 s1
键的值:
declare -A X=(
['s1']="firstname middlename secondname"
['s2']="surname nickname"
['s3']="other"
)
现在我们可以得到 s1
键的值作为数组:
declare -a names=(${X[s1]})
变量names
现在包含数组:
> echo $names
firstname
> echo ${names[1]}
middlename
> echo ${#names[@]}
3
最后,您的问题部分显示了带有 space 的字符串:
"first name"
、"second name"
我们来做个小技巧——把一个space表示成一个特殊的符号序列(也可以只是一个符号),例如双下划线:
"first__name"
, "second__name"
再次声明我们的字典,但在数组元素中使用"escaped" spaces:
declare -A X=(
['s1']="first__name middle__name second__name"
['s2']="surname nickname"
['s3']="other"
)
在这种情况下,我们将 s1
键的值作为数组获得:
declare -a names=(${X[s1]})
我们需要 post 处理我们的数组元素以删除 __
space 对实际 space 的替换符号。为此,我们只需使用 Bash 字符串的替换命令:
> echo ${names/__/ }
first name
> echo ${names[1]/__/ }
middle name
> echo ${#names[@]}
3
一种更符合人体工程学的解决方案,不会强制操作按键。
# your data with spaces
array=(1 '2 with space' 3 "4 with space and ' symbol")
declare -p array
# quote it with " and store it, your data can't contain double quote
declare -A associative=([x]=x [array]=$(printf '"%s" ' "${array[@]}"))
declare -p associative
# get your data in another array
eval deserialized_array=(${associative[array]})
declare -p deserialized_array
echo ${deserialized_array[3]}
# or let bash handle everything
# note: array contain data with double quote character
array=(1 '2 with space' 3 "4 with space and ' \" symbol")
declare -A associative=([x]=x [array]=$(declare -p array))
declare -p associative
array=() # make sure data is gone
# get the data in the same array
eval ${associative[array]}
echo ${array[3]}
我必须使用 Java 工具的输出,它 returns 一个看起来像 HashMap<String, ArrayList<String>
的地图数据结构。我必须使用 BASH 并尝试将其声明为关联数组,这与地图非常相似。 bash 中关联数组的声明应该在一行中,我尝试按如下方式进行。
ARRAY=(["sem1"]=("first name" "second name") ["sem2"]=("third name") ["sem3]=OTHER_LITS)
但这会产生以下错误:
bash: syntax error near unexpected token `('
我可以逐行定义它,但我想把它放在一行中。我如何在 bash 中仅在一行中定义关联数组?
在 BASH 中没有多维数组支持的情况下,您可以使用这个 word-around 关联数组。关联数组中的每个 key
都是 map-index,array-list-index
:
# use one line declaration
declare -A array=([sem1,0]="first name" [sem1,1]="second name" [sem2,0]="third name" [sem3,0]="foo bar")
# loop thrpugh the map array
for i in "${!array[@]}"; do echo "$i => ${array[$i]}"; done
sem2,0 => third name
sem1,0 => first name
sem1,1 => second name
sem3,0 => foo bar
顺便说一句,关联数组、字典或映射 - 都属于一种抽象数据类型(我们称之为 字典)。
因此,这是将 array 作为值存储在 Bash 的 dictionary 中的解决方案(4+ 版本) .
请注意,Bash 中的 array 是 space 分隔的字符串列表(因此元素内部没有任何 space,即字符串),所以我们可以写一个引用列表:
"firstname middlename secondname"
作为 X
字典中 s1
键的值:
declare -A X=(
['s1']="firstname middlename secondname"
['s2']="surname nickname"
['s3']="other"
)
现在我们可以得到 s1
键的值作为数组:
declare -a names=(${X[s1]})
变量names
现在包含数组:
> echo $names
firstname
> echo ${names[1]}
middlename
> echo ${#names[@]}
3
最后,您的问题部分显示了带有 space 的字符串:
"first name"
、"second name"
我们来做个小技巧——把一个space表示成一个特殊的符号序列(也可以只是一个符号),例如双下划线:
"first__name"
, "second__name"
再次声明我们的字典,但在数组元素中使用"escaped" spaces:
declare -A X=(
['s1']="first__name middle__name second__name"
['s2']="surname nickname"
['s3']="other"
)
在这种情况下,我们将 s1
键的值作为数组获得:
declare -a names=(${X[s1]})
我们需要 post 处理我们的数组元素以删除 __
space 对实际 space 的替换符号。为此,我们只需使用 Bash 字符串的替换命令:
> echo ${names/__/ }
first name
> echo ${names[1]/__/ }
middle name
> echo ${#names[@]}
3
一种更符合人体工程学的解决方案,不会强制操作按键。
# your data with spaces
array=(1 '2 with space' 3 "4 with space and ' symbol")
declare -p array
# quote it with " and store it, your data can't contain double quote
declare -A associative=([x]=x [array]=$(printf '"%s" ' "${array[@]}"))
declare -p associative
# get your data in another array
eval deserialized_array=(${associative[array]})
declare -p deserialized_array
echo ${deserialized_array[3]}
# or let bash handle everything
# note: array contain data with double quote character
array=(1 '2 with space' 3 "4 with space and ' \" symbol")
declare -A associative=([x]=x [array]=$(declare -p array))
declare -p associative
array=() # make sure data is gone
# get the data in the same array
eval ${associative[array]}
echo ${array[3]}