You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

提取多文件匹配表头列并补全缺失值的AWK脚本问题

修正AWK脚本实现跨CSV文件提取指定列并填充缺失值

问题描述

现有两个CSV文件,需提取val 2和val 5对应的列,分别写入独立文件;其中file1.csv有5行数据,file2.csv有7行数据,缺失的数值用?填充。

源文件内容

# file1.csv
cat << EOF > file1.csv
val 1, val 2, val 5, val 6
34,12,23,54
22,32,22,43
12,32,11,31
32,32,44,22
32,34,23,45
EOF

# file2.csv
cat << EOF > file2.csv
val 5, val 2, val 3, val 4, val 7
4,82,13,4,33
2,22,42,3,23
1,42,51,1,67
33,42,84,2,43
42,44,93,5,56
23,42,32,32,34
32,43,22,11,2
EOF

原AWK脚本

awk 'BEGIN { FS=", "; OFS=" " }
     NR==FNR {
        if (FNR > 1) {
            val2[FNR-1] = $2
            val5[FNR-1] = $3
        }
        next
     }
     {
        if (FNR > 1) {
            val2[FNR-1] = val2[FNR-1] " " $2
            val5[FNR-1] = val5[FNR-1] " " $5
        }
     }
     END {
        print "val 2"
        for (i=1; i<=NR; i++) {
            if (i <= length(val2)) {
                print val2[i]
            } else {
                print "?"
            }
        }
        print ""
        print "val 5"
        for (i=1; i<=NR; i++) {
            if (i <= length(val5)) {
                print val5[i]
            } else {
                print "?"
            }
        }
     }' file1.csv file2.csv

期望输出

# output_val_2.txt
cat << EOF > output_val_2.txt
12 82
32 22
32 42
32 42
34 44
?  42
?  43
EOF

# output_val_5.txt
cat << EOF > output_val_5.txt
23 4
22 2
11 1
44 33
23 42
?  23
?  32
EOF

修正后的AWK脚本

awk 'BEGIN { FS=", "; OFS=" " }
     # 处理第一个文件file1.csv
     NR==FNR {
         if (FNR == 1) {
             # 动态识别val2和val5的列索引
             for (i=1; i<=NF; i++) {
                 if ($i == "val 2") col2_file1 = i
                 if ($i == "val 5") col5_file1 = i
             }
             next
         }
         row = FNR - 1
         val2[row] = $col2_file1
         val5[row] = $col5_file1
         max_rows = row
         next
     }
     # 处理第二个文件file2.csv
     {
         if (FNR == 1) {
             # 动态识别val2和val5的列索引
             for (i=1; i<=NF; i++) {
                 if ($i == "val 2") col2_file2 = i
                 if ($i == "val 5") col5_file2 = i
             }
             # 更新最大行数为两个文件的较大值
             if ((FNR - 1) > max_rows) max_rows = FNR - 1
             next
         }
         row = FNR - 1
         # 合并数据,缺失位置用?填充
         val2[row] = (row in val2 ? val2[row] : "?") OFS $col2_file2
         val5[row] = (row in val5 ? val5[row] : "?") OFS $col5_file2
         # 更新最大行数
         if (row > max_rows) max_rows = row
     }
     END {
         # 写入val2结果文件
         print "val 2" > "output_val_2.txt"
         for (i=1; i<=max_rows; i++) {
             split(val2[i], parts)
             line = (parts[1] != "" ? parts[1] : "?") OFS (parts[2] != "" ? parts[2] : "?")
             # 对齐格式,?后补两个空格
             if (line ~ /^\? /) line = "?  " parts[2]
             print line > "output_val_2.txt"
         }
         close("output_val_2.txt")
         
         # 写入val5结果文件
         print "val 5" > "output_val_5.txt"
         for (i=1; i<=max_rows; i++) {
             split(val5[i], parts)
             line = (parts[1] != "" ? parts[1] : "?") OFS (parts[2] != "" ? parts[2] : "?")
             if (line ~ /^\? /) line = "?  " parts[2]
             print line > "output_val_5.txt"
         }
         close("output_val_5.txt")
     }' file1.csv file2.csv

关键修正说明

  1. 动态列索引:不再硬编码列位置,通过表头自动识别val 2和val 5在两个文件中的列号,适配列顺序变化。
  2. 正确计算最大行数:取两个文件数据行的最大值(7行)作为循环上限,替代原脚本错误使用的总记录数NR。
  3. 双向缺失值填充:同时处理file1缺失的行(补?在第一个位置)和file2缺失的情况,确保每行都有两个值。
  4. 格式对齐:对包含?的行做格式调整,保证和期望输出的空格对齐一致。
  5. 直接写入文件:将结果直接写入指定的输出文件,无需额外重定向操作。

内容的提问来源于stack exchange,提问作者Kay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 02:00:59