bash - 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"
可能吗?
解决方案
@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
嘿,我确实说过这会有点令人费解!:-)