对行中的某些值求和,但如果这些字段之一为空,则不打印总和

对行中的某些值求和,但如果这些字段之一为空,则不打印总和

我有一个包含 3 列的文件(逗号作为分隔符)。第一列包含 ID,而第二列和第三列包含我想要求和的值。总和应作为第四列附加到输出中的文件中。

但是,在某些情况下,第三列可能为空(例如输入文件的第二行)。在这种情况下,与总和相关的列必须为空。但是,当字段显式显示时0,应照常计算总和(即输入文件的第 4 行)。

  • 输入.txt
    2309,-0.3,0.2
    2311,1.2,
    2312,0,-1
    2315,2.2,0
    
  • 期望的输出:
    2309,-0.3,0.2,-0.1
    2311,1.2,,
    2312,0,-1,-1
    2315,2.2,0,2.2
    

我之前看到过类似的讨论,但我不知道如何指定应在第二列和第三列之间进行求和,以及如何跳过第三列为空的行的求和。下面的脚本应该对同一行中包含的所有值进行求和(还有 ID??),我可以以某种方式修改它,还是您可以建议我另一种更快的方法?

NF++; $NF=sum
awk -v OFS=, -F, 'NR>1{sum=0; for(i=1; i<=NF; i++) sum += $i; NF++; $NF=sum } 1'

答案1

$ awk 'BEGIN{FS=OFS=","} {print $0, ($3=="" ? "" : $2+$3)}' input.txt
2309,-0.3,0.2,-0.1
2311,1.2,,
2312,0,-1,-1
2315,2.2,0,2.2

答案2

$ cat dst
2309,-0.3,0.2,-0.1
2311,1.2,,
2312,0,-1,-1
2315,2.2,0,2.2
$ cat awkscript
#!/bin/sh
awk -F, '
    {
        if ($3 == "") $0 = $0 ","
        else $0 = $0 "," $2+$3
        print $0
    }
' $1 >$2
$  ./awkscript src dst
$ cat dst
2309,-0.3,0.2,-0.1
2311,1.2,,
2312,0,-1,-1
2315,2.2,0,2.2

答案3

使用以下awk程序应该可以实现:

awk 'BEGIN{FS=OFS=","} {sum=0; for (i=2;i<=NF;i++) {if ($i=="") {sum=""; break}; sum+=$i}; $(NF+1)=sum}1' input.txt 

这会

  • 将输入和输出字段分隔符(FSOFS)设置为,
  • 对于每一行,将sum变量重置为0并计算从字段 2 开始的所有字段的总和;但是,如果任何字段显式为空 ( $i==""),它将跳出求和循环并将 设为sum空字符串
  • 然后它会将一个新的附加字段设置为 的值sum(无论是实际总和还是空字符串)。
  • 最后,它会打印当前行,包括所有修改——这就是1规则块之外看似“流浪”的含义。awk如果规则块之外存在任何计算结果为“true”的布尔条件,将打印当前行。

对于您的输入示例,输出是

2309,-0.3,0.2,-0.1
2311,1.2,,
2312,0,-1,-1
2315,2.2,0,2.2

答案4

使用 Miller ( mlr) 而不是awk

$ mlr --csv -N put 'is_not_empty($3) { $4 = $2 + $3 }' then unsparsify file
2309,-0.3,0.2,-0.100000
2311,1.2,,
2312,0,-1,-1
2315,2.2,0,2.200000

这将在任何具有非空第 3 个字段的记录中创建第 4 个字段。unsparsify然后,该操作将在上一步中未创建字段的任何记录中创建缺失的第 4 个字段。

相关内容