Bash 来自字符串的关联数组?
Bash Associative Array from String?
命令发出字符串:“[abc]=kjlkjkl [def]=yutuiu [ghi]=jljlkj”
我想使用这些键|值对加载一个 bash 关联数组,但我得到的结果是一个单行数组,其中键由第一对组成 [abc]=kjlkjkl
并且该值是整个字符串的其余部分,因此:declare -p arr
returns declare -A arr["[abc]=kjlkjkl"]="[def]=yutuiu [ghi]=jljlkj"
这就是我现在正在做的事情。请问我哪里错了?
declare -A arr=()
while read -r a b; do
arr["$a"]="$b"
done < <(command that outputs the string "[abc]=kjlkjkl [def]=yutuiu [ghi]=jljlkj")
您可以使用“eval declare”技巧 - 但请确保您的输入是干净的。
#! /bin/bash
s='[abc]=kjlkjkl [def]=yutuiu [ghi]=jljlkj'
eval declare -A arr=("$s")
echo ${arr[def]} # yutuiu
如果输入不安全,请不要使用。想象一下(不要尝试)如果
会发生什么
s='); rm -rf / #'
将此附加到输出字符串的命令中:
| tr ' =' '\n ' | tr -d '[]'
“正确的”good™ 解决方案是编写您自己的解析器并对输入进行标记化。例如逐字符读取输入字符,处理 [
和 ]
以及 =
和 space 以及可选的引用。解析字符串后,将输出分配给关联数组。
一个简单的方法可以是:
echo "[abc]=kjlkjkl [def]=yutuiu [ghi]=jljlkj" |
xargs -n1 |
{
declare -A arr;
while IFS= read -r line; do
if [[ "$line" =~ ^\[([a-z]*)\]=([a-z]*)$ ]]; then
arr[${BASH_REMATCH[1]}]=${BASH_REMATCH[2]}
fi
done
declare -p arr
}
输出:
declare -A arr=([abc]="kjlkjkl" [ghi]="jljlkj" [def]="yutuiu" )
你需要解析它:在 spaces 上拆分字符串,在等号上拆分每个键值对,并去掉括号。
这是一种方法,使用 tr
将 space 替换为换行符,然后再次 tr
删除所有括号(包括值中出现的任何括号),然后 IFS="="
拆分键值对。我确信这可以更有效地完成,例如使用 AWK 或 Perl,但我不知道如何。
declare -A arr=()
while IFS="=" read -r a b; do
arr["$a"]="$b"
done < <(
echo "[abc]=kjlkjkl [def]=yutuiu [ghi]=jljlkj" |
tr ' ' '\n' |
tr -d '[]'
)
echo "${arr[def]}" # -> yutuiu
请参阅 以了解另一种做法,结合了 space 和 equals 步骤。
命令发出字符串:“[abc]=kjlkjkl [def]=yutuiu [ghi]=jljlkj”
我想使用这些键|值对加载一个 bash 关联数组,但我得到的结果是一个单行数组,其中键由第一对组成 [abc]=kjlkjkl
并且该值是整个字符串的其余部分,因此:declare -p arr
returns declare -A arr["[abc]=kjlkjkl"]="[def]=yutuiu [ghi]=jljlkj"
这就是我现在正在做的事情。请问我哪里错了?
declare -A arr=()
while read -r a b; do
arr["$a"]="$b"
done < <(command that outputs the string "[abc]=kjlkjkl [def]=yutuiu [ghi]=jljlkj")
您可以使用“eval declare”技巧 - 但请确保您的输入是干净的。
#! /bin/bash
s='[abc]=kjlkjkl [def]=yutuiu [ghi]=jljlkj'
eval declare -A arr=("$s")
echo ${arr[def]} # yutuiu
如果输入不安全,请不要使用。想象一下(不要尝试)如果
会发生什么s='); rm -rf / #'
将此附加到输出字符串的命令中:
| tr ' =' '\n ' | tr -d '[]'
“正确的”good™ 解决方案是编写您自己的解析器并对输入进行标记化。例如逐字符读取输入字符,处理 [
和 ]
以及 =
和 space 以及可选的引用。解析字符串后,将输出分配给关联数组。
一个简单的方法可以是:
echo "[abc]=kjlkjkl [def]=yutuiu [ghi]=jljlkj" |
xargs -n1 |
{
declare -A arr;
while IFS= read -r line; do
if [[ "$line" =~ ^\[([a-z]*)\]=([a-z]*)$ ]]; then
arr[${BASH_REMATCH[1]}]=${BASH_REMATCH[2]}
fi
done
declare -p arr
}
输出:
declare -A arr=([abc]="kjlkjkl" [ghi]="jljlkj" [def]="yutuiu" )
你需要解析它:在 spaces 上拆分字符串,在等号上拆分每个键值对,并去掉括号。
这是一种方法,使用 tr
将 space 替换为换行符,然后再次 tr
删除所有括号(包括值中出现的任何括号),然后 IFS="="
拆分键值对。我确信这可以更有效地完成,例如使用 AWK 或 Perl,但我不知道如何。
declare -A arr=()
while IFS="=" read -r a b; do
arr["$a"]="$b"
done < <(
echo "[abc]=kjlkjkl [def]=yutuiu [ghi]=jljlkj" |
tr ' ' '\n' |
tr -d '[]'
)
echo "${arr[def]}" # -> yutuiu
请参阅