
これは簡単な問題だと確信しているので、あらかじめお詫びします。それでも、やってみます。
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
編集1: Sukminderのおかげで、もう少し簡単な方法ができました
$ awk -F+ '{printf("%s+%d\n",$1,sum);sum+=$2}' blah.txt
編集2: もう少し簡潔に、Bernhard に感謝します:
$ awk -F+ '{print $1,sum;sum+=$2}' OFS="+" blah.txt
編集3: しかし、前者では最初の行に 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
。私の知る限り、regular はawk
正規表現からグループを抽出できません。
これは何をするのでしょうか?正規表現 を使用してに一致し$0
、結果を に入れます。これは、次と一致します: - 0 個以上の数字以外の文字に一致し、それを最初の配列インデックスに配置します (括弧はグループ化と呼ばれる処理を担当します)。次に、長さが 0 以外の数値に一致し (それを配列の 2 番目の要素として配置します)。ary
/([^0-9]*)([0-9]+)/
([^0-9]*)
([0-9]+)
もちろん、エラー チェックやマッチングの特殊なケースなどを追加して、これをさらに複雑にすることもできますが、これ (つまり正規表現) については自分で調べてみることをお勧めします。