遍历子目录提取DOE.nas第4列并横向合并输出的问题排查
问题描述
需要遍历多个子目录,提取所有子目录中DOE.nas文件的第4列,将这些列横向并排输出到一个文件中。
示例文件
dir_1/DOE.nas
PSHELL 217 136738 0.7 136738 PSHELL 1786 13571 1.4 13571 PSHELL 1605 136513 0.65 136513 PSHELL 1623 13571 1.4 13571
dir_2/DOE.nas
PSHELL 1628 136733 1.3 136733 PSHELL 2015 136514 0.75 136514 PSHELL 2304 136513 1.5 136513 PSHELL 2509 13571 1.2 13571
期望输出(out.txt)
0.7 1.3 1.4 0.75 0.65 1.5 1.4 1.2
现有代码及错误
执行脚本
for FILE in */*.nas; do awk -v OFS='\t' '{print $4}' "$FILE" > tmp paste tmp >> out.txt done
错误输出
0.7 1.4 0.65 1.4 1.3 0.75 1.5 1.2
解决方法
原代码的问题在于每次循环都会用>覆盖tmp文件,再通过paste tmp >> out.txt追加内容,最终导致所有数据纵向堆叠。以下是两种可行的修复方案:
方法一:临时文件+paste合并
# 清空输出文件 > out.txt # 为每个DOE.nas生成独立临时文件 i=1 for FILE in */*.nas; do awk '{print $4}' "$FILE" > tmp_$i ((i++)) done # 横向合并所有临时文件到输出文件 paste tmp_* > out.txt # 清理临时文件 rm tmp_*
方法二:awk一次性处理(无临时文件)
awk '{ # 记录每个文件对应行的第4列值 col[FILENAME][NR] = $4 # 记录最大行数,避免文件行数不一致时遗漏 if (NR > max_rows) max_rows = NR # 记录所有目标文件 if (!seen[FILENAME]++) files[++n] = FILENAME } END { # 按行输出,每行拼接所有文件的对应列 for (i=1; i<=max_rows; i++) { line = "" for (j=1; j<=n; j++) { # 用sprintf实现对齐,和示例格式匹配 line = line sprintf("%6s", col[files[j]][i]) } print line } }' */*.nas > out.txt
说明
- 方法一逻辑直观,通过独立临时文件存储每个文件的列数据,最后用
paste横向合并,适合新手理解。 - 方法二无需临时文件,用awk数组存储所有数据后统一输出,效率更高。
sprintf("%6s", ...)用于控制输出对齐格式,可根据需求调整参数。
内容的提问来源于stack exchange,提问作者EverLearner
相关产品推荐
相关产品推荐

