移动列的累计总计

移动列的累计总计

提前道歉,因为我确信这是一个简单的问题。尽管如此,还是这样吧。

cat blah.txt
aa+2
bb+4
cc+10
dd+31

我想处理 blah.txt 以生成以下内容:

aa+0
bb+2
cc+6
dd+16

这里的概念是,第一列可能是歌曲列表,第二列可能是歌曲的开始时间。

我的直觉是使用 awk 来完成此操作。我想到了两个带有数字索引的数组,其中存储 $1 和 $2 的运行总计。我的想法是将运行总计的数字索引移动 1。

tail -r blah.txt | 
awk -F "+" '{ for(i=0;i<=NR;i++) arr[i+1]+=$2; farr[i]=$1 } END 
{ for(i=NR+1;i>1;i--) {if (i==NR) {print farr[NR] FS 0 } 
else { print farr[i] FS arr[i]}}}'

这不简洁,而且行不通。首先,我对阵列制作的失败感到困惑。

无论如何,'nuf 说,能有好心人让我摆脱痛苦吗?

汤姆

答案1

干得好:

$ awk -F+ '{sum+=$2;printf("%s+%d\n",$1,sum-$2);}' blah.txt
aa+0
bb+2
cc+6
dd+16

Edit1:这是一个稍微简单的方法,感谢 Sukminder

$ awk -F+ '{printf("%s+%d\n",$1,sum);sum+=$2}' blah.txt

Edit2:稍微简洁一点,感谢 Bernhard:

$ awk -F+ '{print $1,sum;sum+=$2}' OFS="+" blah.txt

Edit3:但前者在第一行不显示 0,所以这里是一个更正且有些压缩的版本,它显示了回答汤姆问题的更短方法(直到一些新评论提出了更好的方法):

$ awk -F+ '{print$1,s+0;s+=$2}' OFS=+ blah.txt

答案2

最好的方法是学习和使用正则表达式,因为将来它会为你省去很多做这类事情的麻烦。

cat blah.txt | gawk 'match($0, /([^0-9]*)([0-9]+)/, ary) {print ary[1] ary[2]-2}'

您必须用移位变量替换最后 2 个。您应该注意 的用法gawk。据我所知,正则awk不能从正则表达式中提取组。

这是做什么的?它对 进行匹配,使用正则表达式$0将结果放入,匹配:- 0 个或多个非数字字符并将其放在第一个数组索引处(括号负责所谓的分组),然后匹配非零长度数字(并将其作为数组的第二个元素)。ary/([^0-9]*)([0-9]+)/([^0-9]*)([0-9]+)

当然,这可以做得更复杂,以及一些错误检查、匹配的特殊情况等 - 但我鼓励您自己探索这一点(即正则表达式)。

相关内容