合并 2 个 CSV 文件以创建一个 CSV 文件,其中多一列差异

合并 2 个 CSV 文件以创建一个 CSV 文件,其中多一列差异

我有 2 个 CSV 文件。让我们打电话1.csv给 他们2.csv

  • 第一个 ( 1.csv) 如下所示:

    1,3543
    23,3632
    12,7665
    1,9795
    32,8793
    35,0290
    
  • 第二个文件 ( 2.txt) 如下所示:

    1,4543
    3,3223
    4,1213
    6,2324
    65,3123
    32,5432
    9,9839
    5,8798
    
  • 最后一列是第一列和第一列output.csv之间的差异1.csv2.txt

    1,3543,1,4543,0
    23,3632,3,3223,20
    12,7665,4,1213,8
    1,9795,6,2324,-5
    32,8793,65,3123,-23
    35,0290,32,5432,3
    ,,9,9839,NA
    ,,5,8798,NA
    

我是 shell 脚本新手。请帮忙

答案1

问题是您没有公共字段来连接这两个文件。您可以即时创建一个,然后再次使用 awk 计算差异,如下所示:

join -a2 -o auto -t, <(awk '{ print NR","$0 }' 1.txt ) <(awk '{ print NR","$0 }' 2.txt) \
    | awk  'BEGIN { 
        FS=OFS="," 
    } 
    { if ($2) { 
        $6=$2-$4 
    } else { 
        $6="NaN" 
    }; 
    print $2,$3,$4,$5,$6  
}'
1,3543,1,4543,0
23,3632,3,3223,20
12,7665,4,1213,8
1,9795,6,2324,-5
32,8793,65,3123,-33
35,0290,32,5432,3
,,9,9839,NaN
,,5,8798,NaN

答案2

如果将两个文件粘贴在一起,则可以处理整体结果:

paste -d, 1.txt 2.txt |
awk -F, 'NF < 4  { printf $1=="" ? ",%s,NA\n" : "%s,,NA\n", $0 }
         NF >= 4 { printf "%s,%d\n", $0, $1-$3 }'

这使用逗号连接两个文件;在其他文件中没有匹配的行将导致短行,要么以空字段开头(如果第二个文件较长),要么以空字段结尾(如果第一个文件较长)。使用 AWK 处理结果:

  • 如果字段数小于4,则数据丢失;输出带有额外字段(前置或附加)的行,并附加“NA”
  • 如果字段数量为4个或更多,则所有数据都存在;输出该行后跟字段 1 和 3 之间的差异。

答案3

paste -d : 1.txt 2.txt |
awk -F : -v OFS=, '
{
    split($1,a,OFS)
    split($2,b,OFS)

    $1 = a[1]; $2 = a[2]
    $3 = b[1]; $4 = b[2]
}

{
    $5 = $1 == "" || $3 == "" ? "NA" : $1 - $3
}; 1'

:这会使用 .a 作为分隔符并排连接两个文件paste

awk命令分为预处理块和计算块。

预处理块确保每条记录有四个字段;每个文件中两个。

它采用每个输入行的两个:- 分隔字段,并将每个输入行中以逗号分隔的子字段提取到两个数组a和中b。每个数组中预期的两个元素直接转移到前四个字段中。每当其中一个文件比另一个文件短时,这将生成空字段。

第二个块将第 5 个字段计算为第 1 个字段和第 3 个字段之间的差,除非其中一个字段为空,在这种情况下,第 5 个字段被分配字符串NA


只是想一下预处理块如何推广到任意数量的输入文件,每个文件中具有任意固定数量的字段......

paste -d : 1.txt 2.txt |
awk -F : -v OFS=, -v nf=2 '
{
    for (i = NF; i >= 1; --i) {
        split($i,a,OFS)
        for (j = 1; j <= nf; ++j)
            $((i-1)*nf + j) = a[j]
    }
}

{
    $5 = $1 == "" || $3 == "" ? "NA" : $1 - $3
}; 1'

这通过将每个文件中的预期字段数作为nf命令行上的参数并nf从每个:- 分隔的输入字段(无论是否为空)分配这些字段来解决这个问题。

最后的计算块与以前相同,因为我们只是使awk代码的第一部分更加灵活,以便将来更改需求或在其他地方重用的可能性。

答案4

paste g1.txt  g2.txt|awk '{print $1","$2}'| awk -F "," '{if (NF==4){print $0","$1-$3}else{print ",,"$0"NA"}}'

输出

1,3543,1,4543,0
23,3632,3,3223,20
12,7665,4,1213,8
1,9795,6,2324,-5
32,8793,65,3123,-33
35,0290,32,5432,3
,,9,9839,NA
,,5,8798,NA

相关内容