提前道歉,因为我确信这是一个简单的问题。尽管如此,还是这样吧。
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]+)
当然,这可以做得更复杂,以及一些错误检查、匹配的特殊情况等 - 但我鼓励您自己探索这一点(即正则表达式)。