如何解决grep输出存入Bash数组时被冒号拆分的问题
问题描述
我有一个内容如下的文件:
{ [commandA]: cmdA, [commandB]: cmdB, ... }
我希望通过grep提取包含命令的行并存储到Bash数组中。但执行以下命令:
cmdFunMap=(`grep "^ \[command" myfile`) printf '%s\n' "${cmdFunMap[@]}"
得到的结果是:
[commandA]: cmdA, [commandB]: cmdB,
而非预期的:
[commandA]: cmdA, [commandB]: cmdB,
我尝试匹配整行,命令如下:
cmdFunMap=(`grep "^ \[command.*$" myfile`) printf '%s\n' "${cmdFunMap[@]}"
还尝试将IFS设置为\n,但结果依旧相同。我的环境是Bash v5.0.17(1)-release (x86_64-pc-linux-gnu),Ubuntu 20.04.3 LTS(WSL)。另外在Alpine 3.15.4中测试,行为一致。请问如何修复这种冒号拆分的问题?
解决办法
方法1:使用readarray(推荐,Bash 4.0+可用)
直接将grep的输出按行读取到数组,不会拆分每行内容:
readarray -t cmdFunMap < <(grep "^ \[command" myfile) printf '%s\n' "${cmdFunMap[@]}"
readarray -t:自动移除每行末尾的换行符,确保数组元素是干净的行内容< <(...):进程替换,把grep的输出作为readarray的输入,实现按行读取
方法2:使用while循环逐行读取(兼容低版本Bash)
如果你的Bash版本低于4.0,用循环逐行添加数组元素:
cmdFunMap=() while IFS= read -r line; do cmdFunMap+=("$line") done < <(grep "^ \[command" myfile) printf '%s\n' "${cmdFunMap[@]}"
IFS=:保留行内的空格和特殊字符,避免截断read -r:禁用反斜杠转义,确保原始内容被正确读取
问题原因解析
之前用反引号cmdFunMap=(grep ...)的方式会触发Bash的分词机制:命令替换的输出会被按照IFS中的分隔符(默认含空格、制表符、换行)拆分,哪怕手动设置IFS=$'\n',行内的空格依然会导致拆分——因为命令替换的分词逻辑不仅受IFS影响,还会默认按空白符分割内容。本质上,命令替换不适合用来读取多行内容到数组,readarray或while循环才是可靠的方案。
内容的提问来源于stack exchange,提问作者E-Newman
相关产品推荐
相关产品推荐

