如何将文件读取的数据正确追加到bash数组中
问题根因
这是bash管道的子shell机制导致的:bash默认会为管道符|两侧的命令创建独立的子shell进程运行,你写的while read循环属于管道右侧的命令,全程在子shell中执行,循环内对tms数组的所有修改仅在子shell内生效。循环结束后子shell直接销毁,父shell中定义的tms数组从未被修改,因此最终打印为空。你的数组追加语法本身没有错误,问题出在变量作用域上。
可用解决方案
方案1:进程替换规避子shell(兼容绝大多数bash版本)
用进程替换语法替代管道输入,让while循环直接在当前父shell进程中执行,对数组的修改会被正常保留:
declare -a tms while read -r next_line do echo "$next_line" tms+=("$next_line") done < <(head thefiles.txt | cut -d ' ' -f 9) # 验证数组内容 echo "${tms[@]}"
写法说明:
read加-r参数是为了避免反斜杠等特殊字符被自动转义,变量引用加双引号可以规避带空格的内容拆分异常,属于bash的标准规范写法。
方案2:mapfile直接读入数组(最优最简实现)
bash内置的mapfile(别名readarray)是专门用于将多行输入直接读入数组的命令,不需要手写循环,也不会触发子shell问题:
# -t参数用于自动移除每行末尾的换行符 mapfile -t tms < <(head thefiles.txt | cut -d ' ' -f 9)
执行完后直接打印"${tms[@]}"就能看到全部存入的时间戳,代码简洁且执行效率更高。
方案3:开启lastpipe选项(仅适用于特定场景)
bash 4.2及以上版本支持lastpipe配置项,开启后管道的最后一个命令会在当前shell进程中运行,原有代码结构不需要大改就能生效:
# 开启配置 shopt -s lastpipe declare -a tms head thefiles.txt | cut -d ' ' -f 9 | while read -r next_line do echo "$next_line" tms+=("$next_line") done
该方案依赖shell配置,换环境后容易失效,不推荐作为首选方案。
额外提示:
ls -l的输出会根据文件名长度、终端宽度自动调整列间空格数量,直接用cut -d ' '按单个空格分割很容易取错列。更稳妥的文件时间获取方式是直接用stat命令读取文件元数据,不要解析格式不稳定的ls输出。
你之前尝试的错误写法说明
tms+=(next_line):变量前未加$取值符,会把固定字符串next_line作为元素追加到数组,不会读取变量内容tms+=(${next_line[@]}):next_line是普通字符串变量不是数组,这种数组式展开属于冗余写法,没有实际作用
内容的提问来源于stack exchange,提问作者bob.sacamento
相关产品推荐
相关产品推荐

