如何从grep命令结果创建Bash关联数组?
解决Bash关联数组填充问题
我的grep命令得到如下数据:
$ grep match data.txt match key1 value1 match key2 value2 match key3 value3
我希望得到一个等价于以下代码的关联数组:
declare -A map=( ["key1"]="value1" ["key2"]="value2" ["key3"]="value3")
我已成功使用awk提取键和值,示例如下:
$ grep match data.txt | awk '{print $2}' key1 key2 key3
我尝试填充关联数组,但不清楚正确语法:
$ declare -A map $ grep match data.txt | map[$(awk '{print $2}')]=$(awk '{print $3}') # doesn't work
正确的实现方法
方法1:用while read循环(推荐,避免子shell问题)
declare -A map # 用进程替换把grep结果传给while循环,避免子shell导致数组无法在父环境生效 while read -r _ key value; do map["$key"]="$value" done < <(grep match data.txt)
read -r _ key value中,_用来接收第一列的match字符串,忽略不用;key和value分别捕获第二、第三列内容< <(grep ...)是Bash的进程替换语法,能让循环在当前shell执行,赋值的数组会保留下来
方法2:用awk生成赋值语句再执行
declare -A map # 用awk生成每个键值对的赋值命令,通过eval执行 eval "$(grep match data.txt | awk '{printf "map[\"%s\"]=\"%s\"; ", $2, $3}')"
- awk会输出
map["key1"]="value1"; map["key2"]="value2"; ...这样的字符串 eval会把这些字符串当作Bash命令执行,完成数组填充
原方法失效的原因
- 管道导致子shell:通过
|连接命令时,右侧的赋值操作会在子shell中执行,父shell的map数组不会被修改 - 批量处理错误:
$(awk '{print $2}')会把所有行的key合并成一个字符串(比如key1key2key3),同理value也是,这样赋值的数组键值完全不符合预期
内容的提问来源于stack exchange,提问作者Aboelseoud
相关产品推荐
相关产品推荐

