我有一个包含 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
这会
- 将输入和输出字段分隔符(
FS
和OFS
)设置为,
- 对于每一行,将
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 个字段。