移動列の累積合計

移動列の累積合計

これは簡単な質問なので事前にお詫び申し上げます。それでもそうです。

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

blah.txtを処理して以下を生成したいと思います。

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

ここでの概念は、最初の列が曲のリストになり、2番目の列が曲の開始時刻になる可能性があることです。

私の本能は、これを達成するためにawkを使用することです。私は$ 1と$ 2の累計を格納する数値インデックスを持つ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]}}}'

きれいでも動作しません。まず、アレイの製造に失敗して混乱しています。

とにかく、どんなフレンドリーな魂が私を不幸から救うことができますか?

トム

答え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

編集3:しかし、前者は最初の行にゼロを表示しないので、ここにTomの質問に答えるより短い方法を示す修正され、やや圧縮されたバージョンがあります(いくつかの新しいコメントがより良い方法を提案するまで) 。

$ 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の数値(そしてそれを配列の2番目の要素にします)。ary/([^0-9]*)([0-9]+)/([^0-9]*)([0-9]+)

もちろん、これはいくつかのエラーチェック、一致のための特別なケースなどによってより複雑にすることができます。しかし、この問題は直接探索してください(例:正規表現)。

関連情報