我想通过添加子日值并生成统一的每日数据,从混合的每日和子日数据中准备统一的每日数据。我的示例输入和所需的输出数据如下所示。
输入文件:
date Value
01/01/2000 2
01/01/2000 2
01/02/2000 6
01/03/2000 5
01/03/2000 4
所需的输出文件:
date Value
01/01/2000 4 (i.e. 2+2)
01/02/2000 6
01/03/2000 9(i.e 5+4)
答案1
答案2
您可以使用 AWK 及其关联数组来执行此操作:
awk '{
if (NR == 1) { print $0 }
else { count[$1] += $2 }
}
END {
# Sort the items based on the date
n = asorti(count, indices)
for (i = 1; i <= n; i++) {
print indices[i], count[indices[i]]
}
}' < file_name
当所有记录都处理完毕后,该END
块将在最后执行。
数组的排序已从这个帖子。
答案3
您可以使用以下awk
脚本:
$ awk '
{ a[$1]+=$2 }
END{ for(val in a) printf("%s %s\n", val, a[val]) }
' <(tail -n +2 sample.txt)
然而,使用这种方法将不再保留输出的顺序。只要数据按日期数字顺序排列,sort
最后的简单操作就会重新调整输出。
例子
假设样本数据。
$ cat sample.txt
date Value
01/01/2000 2
01/01/2000 2
01/02/2000 6
01/03/2000 5
01/03/2000 4
上述脚本将生成如下结果:
$ awk '
{ a[$1]+=$2 }
END{ for(val in a) printf("%s %s\n", val, a[val]) }
' <(tail -n +2 sample.txt)
01/02/2000 6
01/01/2000 4
01/03/2000 9
运行输出sort
将重新调整数据。
$ awk '
{ a[$1]+=$2 }
END{ for(val in a) printf("%s %s\n", val, a[val]) }
' <(tail -n +2 sample.txt)|sort
01/01/2000 4
01/02/2000 6
01/03/2000 9
原始文件中的标头可以这样添加回来:
$ (head -n 1 sample.txt; awk '{a[$1]+=$2}END{for(val in a) printf("%s %s\n", val, a[val])}' <(tail -n +2 sample.txt)|sort)
date Value
01/01/2000 4
01/02/2000 6
01/03/2000 9
您可以将其展开一点,以便更容易阅读:
$ (
head -n 1 sample.txt
awk '
{ a[$1]+=$2 }
END{ for(val in a) printf("%s %s\n", val, a[val]) }
' <(tail -n +2 sample.txt) | sort
)
date Value
01/01/2000 4
01/02/2000 6
01/03/2000 9
更新#1
根据评论中 @StephaneChazelas 的反馈,我进一步简化了我的示例。能够通过使用这个()tail ...
将其移动到块内来消除 。这将跳过第一行。awk
NR==1{ next }
sample.txt
我还移动了块| sort
内的位置END{...}
。这仍然会根据日期重新调整数据sort
生成的输出。awk
由于awk
现在调用/bin/sort
它,所以用双引号括起来。
$ awk '
NR==1{ print; next }
{ a[$1]+=$2 }
END{ for(val in a) print val, a[val] | "sort" }
' sample.txt
)
date Value
01/01/2000 4
01/02/2000 6
01/03/2000 9
答案4
我会在 Perl 中这样做:
perl -ane '$.==1 && do{$first=$_; next}; $k{$F[0]}+=$F[1]; END{foreach (keys(%k)){print "$_\t$k{$_}\n"}}' file
01/01/2000 4
01/03/2000 9
01/02/2000 6
这种方法的优点是不需要按时间顺序对行进行排序。