Bash脚本数组去重后长度为1而非预期3的原因咨询
问题成因
长度统计异常的根因是全局IFS配置与数组拆分逻辑不匹配:
- 你在脚本中手动将
IFS(Bash用于字符串拆分的内部字段分隔符)设置为仅包含空格' ' - 去重管道
echo ${hostArray[@]} | tr ' ' '\n' | sort | uniq的输出为每行一个主机名,元素间的分隔符是换行符\n,而非空格 - 数组赋值
unique_words=(...)时,Bash仅会按当前IFS内包含的字符拆分命令替换的返回结果,由于换行符不在当前IFS的拆分规则中,整段输出会被识别为单个字符串存入数组第0位,因此数组长度返回1 - 直接打印
unique_words时视觉上正常,是因为echo输出时会自动将换行符渲染为空格,制造了元素拆分正确的假象。可执行echo "${unique_words[1]}"验证,该下标对应内容为空,所有主机名都存储在unique_words[0]中。
解决方案
以下三种写法均可修复问题,按稳妥度排序:
- 最稳妥方案:使用
mapfile直接按行读取命令输出到数组,完全不受IFS配置干扰# -t 参数自动移除每行末尾的换行符;sort -u 等价于 sort|uniq,执行效率更高 mapfile -t unique_words < <(echo "${hostArray[@]}" | tr ' ' '\n' | sort -u) - 轻量修复方案:给数组赋值时临时指定IFS为换行,不改变全局IFS配置
# 仅本次赋值操作使用换行作为分隔符,执行完成后自动恢复原有IFS规则 IFS=$'\n' unique_words=($(echo "${hostArray[@]}" | tr ' ' '\n' | sort -u)) - 高性能方案(适用于Bash 4.0及以上版本):使用关联数组原生去重,无需调用tr、sort等外部命令,处理大列表时速度优势明显
declare -A host_set for host in "${hostArray[@]}"; do host_set["$host"]=1 done unique_words=("${!host_set[@]}")
修复后执行echo ${#unique_words[@]}即可得到预期返回值3。
内容的提问来源于stack exchange,提问作者Lily Qiang
相关产品推荐
相关产品推荐

