Kumulierte Summen mit verschobener Spalte

Kumulierte Summen mit verschobener Spalte

Ich entschuldige mich schon mal im Voraus, da ich sicher bin, dass es sich hier um ein einfaches Problem handelt. Nichtsdestotrotz, los geht’s.

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

Ich möchte blah.txt verarbeiten, um Folgendes zu erstellen:

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

Die Idee dahinter ist, dass die erste Spalte eine Liste von Liedern sein könnte und die zweite deren Startzeiten.

Ich hatte das Gefühl, dies mit awk zu tun. Ich dachte an zwei Arrays mit numerischen Indizes, die $1 und die laufende Summe von $2 speichern. Meine Idee war, den numerischen Index für die laufenden Summen um 1 zu verschieben.

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]}}}'

Das ist nicht prägnant und funktioniert außerdem nicht. Mich verwirrt vor allem das Versagen bei der Array-Erstellung.

Wie dem auch sei, genug gesagt, könnte mich bitte eine freundliche Person von meinem Elend erlösen?

Tom

Antwort1

Bitte schön:

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

Edit1: hier ist ein etwas einfacherer Weg, danke an Sukminder

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

Edit2: Und noch etwas prägnanter, danke an Bernhard:

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

Edit3: aber ersteres zeigt in der ersten Zeile keine 0 an, daher hier eine korrigierte und etwas komprimierte Version, die den kürzeren Weg zeigt, Toms Frage zu beantworten (bis ein neuer Kommentar einen besseren vorschlägt):

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

Antwort2

Der beste Weg hierzu besteht darin, reguläre Ausdrücke zu lernen und zu verwenden, da Ihnen dies in Zukunft eine Menge Ärger bei derartigen Aufgaben erspart.

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

Sie müssen die letzten 2 durch Ihre Shift-Variable ersetzen. Sie sollten die Verwendung von beachten gawk. Soweit ich weiß, awkkönnen reguläre Ausdrücke keine Gruppen extrahieren.

Was bewirkt dies? Es führt eine Übereinstimmung mit durch $0und fügt Ergebnisse aryunter Verwendung eines regulären Ausdrucks ein /([^0-9]*)([0-9]+)/, der übereinstimmt mit: ([^0-9]*)- 0 oder mehr Zeichen, die keine Zahlen sind, und fügt es an den ersten Array-Index ein (Klammern sind für das sogenannte Gruppieren verantwortlich), dann ([0-9]+)gleicht es eine Zahl mit einer Länge ungleich Null ab (und fügt sie als zweites Element des Arrays ein).

Dies kann natürlich noch ausgefeilter gestaltet werden, zusammen mit einigen Fehlerprüfungen, speziellen Übereinstimmungsfällen usw. – aber ich ermutige Sie, dies (insbesondere reguläre Ausdrücke) selbst zu erkunden.

verwandte Informationen