如何在Bash 3.2(macOS)中将键值对字符串转为数组并按键取值
在Bash 3.2(macOS)中解析键值对字符串并实现按键取值
需求说明
有一批类似以下格式的字符串(来自JSON的result字段),需要解析后能直接通过键名获取对应值:
"result":"guid=guid1;forename=Jimmy Harry;surname=Jones;birthdate=20220201" "result":"guid=guid2;forename=Sarah-Smith;middlename=;surname=Jones;birthdate=20220201"
目标是实现类似Java中按键取值的效果,而非遍历数组逐一匹配键名。
原代码问题分析
你提供的代码存在以下问题:
- 数组拆分错误:
array=($(echo "$result" | tr ';' '\n'))会把值中的空格也当作分隔符,导致Jimmy Harry被拆成两个数组元素,破坏键值对结构。 - 遍历逻辑错误:
for item in $array会按空白符展开数组,正确的遍历应该用for item in "${array[@]}"来保留每个键值对的完整性。 - 条件判断错误:
[[ $item == "forename*" ]]中的引号会让通配符*失效,应改为[[ $item == forename=* ]]才能匹配以forename=开头的键值对。 - 变量引用错误:
${item[counter]}是错误用法,item是单个字符串而非数组,直接使用$item即可。
解决方案
由于Bash 3.2不支持关联数组(Bash 4+才引入),可以通过以下两种方式模拟按键取值:
方案1:用函数实现按键查询
这种方法兼容性最好,支持键名含特殊字符、值含空格的场景:
# 定义按键取值函数 get_kv_value() { local target_key="$1" local kv_list="$2" # 拆分键值对为数组(保留值中的空格) IFS=';' read -ra kv_pairs <<< "$kv_list" # 遍历查找目标键 for kv in "${kv_pairs[@]}"; do if [[ "$kv" == "$target_key="* ]]; then # 截取键名后的内容作为值返回 echo "${kv#$target_key=}" return 0 fi done # 未找到键时返回空字符串 echo "" return 1 } # 使用示例 # 提取JSON中的result值(假设已将result字段内容存入变量) result_str="guid=guid1;forename=Jimmy Harry;surname=Jones;birthdate=20220201" # 获取指定键的值 echo "forename: $(get_kv_value forename "$result_str")" echo "guid: $(get_kv_value guid "$result_str")" echo "birthdate: $(get_kv_value birthdate "$result_str")"
方案2:动态赋值为变量(键名需符合变量规则)
如果键名是合法的Bash变量名(无空格、特殊字符),可以直接将键值对转为变量,实现直接通过变量名取值:
result_str="guid=guid1;forename=Jimmy Harry;surname=Jones;birthdate=20220201" # 拆分键值对为数组 IFS=';' read -ra kv_pairs <<< "$result_str" # 遍历赋值变量 for kv in "${kv_pairs[@]}"; do # 跳过无效的键值对(无=的情况) if [[ "$kv" == *=* ]]; then # 拆分键和值 key="${kv%%=*}" value="${kv#*=}" # 动态赋值变量(注意:如果值含特殊字符需额外处理) eval "$key='$value'" fi done # 直接使用变量取值 echo "forename: $forename" echo "guid: $guid" echo "birthdate: $birthdate"
关键知识点
IFS=';' read -ra kv_pairs <<< "$str":用分号作为分隔符拆分字符串到数组,-r防止反斜杠被转义,-a指定赋值到数组,能保留值中的空格。${kv#$target_key=}:从字符串开头删除匹配$target_key=的部分,得到对应的值。${kv%%=*}:从字符串末尾向前匹配第一个=,截取左边的键名;${kv#*=}从开头匹配第一个=,截取右边的值。
内容的提问来源于stack exchange,提问作者MisterIbbs
相关产品推荐
相关产品推荐

