我正在使用 bash 创建一个脚本来查找、分组和求和 CSV 文件中的字段。每行都有以逗号分隔的字段,每个字段都遵循类似的约定。对于每个逗号分隔的字段,都有一个数字值,然后是一个等号 (=),然后是一个字母数字值。 “(number)=”可能会或可能不会出现在一行中,如果出现,字段位置可能会有所不同,但在行中仅出现一次。另外,等号后面的值的长度也会有所不同。
我的目标的一个例子是最好的。 CSV 文件:
35=D,11=ABCD1,1=ABC,55=XYZ,38=100,40=P,18=M,54=1,59=0,10=111
35=D,11=ABCD2,1=ABC,55=XYZ,40=P,18=M,38=200,54=1,44=10.00,59=0,10=133
35=D,11=ABCD3,1=ABC,55=XYZ,40=P,18=M B,54=1,38=300,44=10.00,59=0,110=200,10=113
35=D,11=ABCD4,1=ABC,55=XYZ,38=400,40=P,18=M B F,54=1,44=10.00,59=0,110=300,10=144
35=D,11=ABCD5,1=ABC,55=ZYX,38=300,40=2,54=1,44=10.00,59=3,10=132
35=D,11=ABCD6,1=ABC,55=ZYX,38=100,40=1,18=C,54=2,59=3,10=131
我想要一个脚本来识别以“38=”开头的每个字段,然后对“=”后面的每个数值进行求和,并按每个“55=”进行分组。每行都会有一个“38=”和一个“55=”。
使用上述文件的输出将是(排序是可选的):
55=XYZ 38=1000
55=ZYX 38=400
答案1
使用米勒http://johnkerl.org/miller/doc,从此开始input.csv
35=D,11=ABCD1,1=ABC,55=XYZ,38=100,40=P,18=M,54=1,59=0,10=111 35=D,11=ABCD2,1=ABC,55=XYZ,40=P,18=M,38=200,54=1,44=10.00,59=0,10=133 35=D,11=ABCD3,1=ABC,55=XYZ,40=P,18=M B,54=1,38=300,44=10.00,59=0,110=200,10=113 35=D,11=ABCD4,1=ABC,55=XYZ,38=400,40=P,18=M B F,54=1,44=10.00,59=0,110=300,10=144 35=D,11=ABCD5,1=ABC,55=ZYX,38=300,40=2,54=1,44=10.00,59=3,10=132 35=D,11=ABCD6,1=ABC,55=ZYX,38=100,40=1,18=C,54=2,59=3,10=131
和跑步
mlr --ofs " " unsparsify then stats1 -a sum -f 38 -g 55 then rename 38_sum,38 input.csv
你将会拥有
55=XYZ 38=1000 55=ZYX 38=400
答案2
Steeldriver 有点打败了我,但我想出了
perl -F'[=,]' -lane '
%row = @F;
$sum{$row{55}} += $row{38};
}{
print "$_ = $sum{$_}" for keys %sum
' file.csv
XYZ = 1000
ZYX = 400
答案3
这是一个awk
解决方案。
awk -F, '{for(a=1;a++<=NF;){
if($a~/^55=/){l=$a}
if($a~/^38=/){b[l]+=substr($a,4)}
}}END{for(x in b){print x,"38="b[x]}}' inp
for(a=1;a++<=NF;){
- 循环遍历每个逗号分隔的字段if($a~/^55=/){l=$a}
- 如果我们找到一个以 开头的字段,55=
则将其存储在变量中l
if($a~/^38=/){b[l]+=substr($a,4)}
- 如果我们找到一个以 开头的字段,则38=
获取后面的值=
并将其累积到 array 中b
,使用变量l
作为键}}END{for(x in b){print x,"38="b[x]}}
- 只打印数组的内容
答案4
怎么样
awk -F, '
{for (i=1; i<=NF; i++) {split ($i, T, "=")
if (T[1] == 55) IX = T[2]
if (T[1] == 38) NM = T[2]
}
SUM[IX] += NM
}
END {for (s in SUM) print "55=" s, "38=" SUM[s]
}
' file
55=ZYX 38=400
55=XYZ 38=1000
遍历所有字段以查找相关字段,拆分为T
数组,如果55
找到,则提取索引,如果38
找到,则提取被加数。循环结束后,进行求和。在END
部分中,显示所有汇总值及其索引。