首页 > 解决方案 > Bash:将两个字符串直接拆分为关联数组

问题描述

我有两个相同数量的子字符串除以分隔符。

我需要从子字符串创建键值对。

简短示例:输入:

firstString='00011010:00011101:00100001'
secondString='H:K:O'
delimiter=':'

期望的结果:

${translateMap['00011010']} -> 'H'
${translateMap['00011101']} -> 'K'
${translateMap['00100001']} -> 'O'

所以,我写道:

IFS="$delimiter" read -ra fromArray <<< "$firstString"
IFS="$delimiter" read -ra toArray <<< "$secondString"
declare -A translateMap

curIndex=0
for from in "${fromArray[@]}"; do
    translateMap["$from"]="${toArray[curIndex]}"
    ((curIndex++))
done

有没有办法直接从 2 个字符串创建关联数组,而不需要不需要的数组和循环?就像是:

IFS="$delimiter" read -rA translateMap["$(read -ra <<< "$firstString")"] <<< "$secondString"

可能吗?

标签: bashsplitassociative-array

解决方案


@accdias 通过declare -A命令分配值的答案的一个(有点令人费解的)变体,但每个步骤都需要一些解释......

首先,我们需要为每个项目将 2 个变量分成单独的行:

$ echo "${firstString}" | tr "${delimiter}" '\n'
00011010
00011101
00100001

$ echo "${secondString}" | tr "${delimiter}" '\n'
H
K
O

这样做的好处是我们现在可以将这两组键/值对作为单独的文件处理。

注意:对于本次讨论的其余部分,我将替换"${delimiter}"':'以使这一点(但不多)不那么复杂。

接下来我们使用paste命令将我们的 2 个“文件”合并到一个文件中;我们还将指定 ']' 作为键/值映射之间的分隔符:

$ paste -d ']' <(echo "${firstString}" | tr ':' '\n') <(echo "${secondString}" | tr ':' '\n')
00011010]H
00011101]K
00100001]O

我们现在将通过几个sed模式运行这些结果来构建我们的数组分配:

$ paste -d ']' <(echo "${firstString}" | tr ':' '\n') <(echo "${secondString}" | tr ':' '\n') | sed 's/^/[/g;s/]/]=/g'
[00011010]=H
[00011101]=K
[00100001]=O

我们现在想做的是在typeset -A命令中使用这个输出,但不幸的是我们需要构建整个命令然后eval它:

$ evalstring="typeset -A kv=( "$(paste -d ']' <(echo "${firstString}" | tr ':' '\n') <(echo "${secondString}" | tr ':' '\n') | sed 's/^/[/g;s/]/]=/g')" )"

$ echo "$evalstring"
typeset -A kv=( [00011010]=H
[00011101]=K
[00100001]=O )

如果我们想删除回车并放在一行中,我们tr在命令的输出中附加另一个sed

$ evalstring="typeset -A kv=( "$(paste -d ']' <(echo "${firstString}" | tr ':' '\n') <(echo "${secondString}" | tr ':' '\n') | sed 's/^/[/g;s/]/]=/g' | tr '\n' ' ')" )"

$ cat "${evalstring}"
typeset -A kv=( [00011010]=H [00011101]=K [00100001]=O )

此时我们可以eval自动生成typeset -A命令:

$ eval "${evalstring}"

现在循环遍历显示键/值对的数组:

$ for i in ${!kv[@]}; do echo "kv[${i}] = ${kv[${i}]}"; done
kv[00011010] = H
kv[00100001] = O
kv[00011101] = K

嘿,我确实说过这会有点令人费解!:-)


推荐阅读