
先道歉,因為我確信這是一個簡單的問題。儘管如此,還是這樣吧。
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,所以這裡是一個更正的且有些壓縮的版本,它顯示了回答 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
,將結果放入ary
,使用正則表達式/([^0-9]*)([0-9]+)/
,匹配:([^0-9]*)
- 0 個或多個非數字字元並將其放在第一個數組索引處(括號負責所謂的分組),然後([0-9]+)
匹配非零長度數字(並將其作為數組的第二個元素)。
當然,這可以做得更複雜,以及一些錯誤檢查、匹配的特殊情況等 - 但我鼓勵您自己探索這一點(即正則表達式)。