Wie formatiere ich die Ausgabe mit dem Befehl Awk printf richtig?

Ich habe die folgende Datei:

echo filename dfT08r352|30.5|2010/06/01|2016/08/29|2281|6.24503764544832|74.9404517453799| zm00dr121|37|2008/03/05|2011/09/12|1285.95833333333|3.52076203513575|42.249144421629| ccvd00121|41.6|2008/03/05|2012/03/05|1461|4|48| sddf00121|39.6|2008/03/05|2012/09/10|1649.95833333333|4.51733972165184|54.208076659822| fttt00121|41|2008/03/05|2013/09/16|2020.95833333333|5.53308236367785|66.3969883641342| ghhyy0121|42.2|2008/03/05|2014/03/18|2203.95833333333|6.03410905772302|72.4093086926762| 

Ich versuche, diese Datei zu formatieren Verwenden Sie awk printf, um das folgende gewünschte Format zu erhalten:

  1. Behalten Sie die gleiche Reihenfolge der Felder bei (links -> rechts).
  2. haben Komma „,“ FS
  3. nur für die drei Felder ($ 5, $ 6, $ 7) mit allen 4-stelligen Zahlen, Wenn weniger eine führende Null und nur 2 Ziffern nach dem Punkt wie 0123.12 oder 1234.10 haben

Ich habe den folgenden awk-Befehl geschrieben

awk -F"|" "{print $1","$2","$3","$4}{format = "%04.2f,%04.2f,%04.2f,"}{printf format, $5,$6,$7}" filename 

Die folgende Ausgabe weist jedoch die folgenden Probleme auf:

  1. ist nicht in Ordnung (links -> rechts)

  2. habe nicht die führende Null

    dfT08r352,30.5,2010/06/01,2016/08/29 2281.00,6.25,74.94,zm00dr121,37,2008/03/05,2011/09/12 1285.96,3.52,42.25,ccvd00121,41.6,2008/03/05,2012/03/05 1461.00,4.00,48.00,sddf00121,39.6,2008/03/05,2012/09/10 1649.96,4.52,54.21,fttt00121,41,2008/03/05,2013/09/16 2020.96,5.53,66.40,ghhyy0121,42.2,2008/03/05,2014/03/18 

Kann mir bitte jemand mitteilen, was mein Fehler ist und wie er behoben werden kann?

Kommentare

  • FYI, für die Kommatrennung ohne Angabe jedes Kommas können Sie 'BEGIN {OFS=","}' oder nur

– aber das ' beantwortet Ihre umfassendere Frage nicht.

Antwort

Sie haben die Felder in der richtigen Reihenfolge, aber Ihre erste Druckanweisung fügt eine neue Zeile (Output Record Separator) hinzu, sodass Ihre Daten vorhanden sind, aber nur unerwartet umbrochen werden.

Das zweite Problem ist, dass Sie printf anweisen, eine Breite von 4 zu verwenden. Dazu gehören der Dezimalpunkt und die beiden darauf folgenden Ziffern, wobei nur eine für die führende Ziffer und keine für die Auffüllung übrig bleibt. Versuchen Sie, 5 als Breite zu verwenden, damit Ihre Daten mit bis zu vier Gesamtzahlen aufgefüllt werden. Wenn Sie 4 Stellen vor dem Dezimalpunkt möchten, ändern Sie stattdessen die Breite auf 7.

Dies ist die kürzeste Änderung, die ich von Ihrem Programm an etwas vorgenommen habe, das das ausgibt, was ich denke wollen:

awk -F"|" "{ format = "%05.2f,%05.2f,%05.2f"; print $1","$2","$3","$4"," sprintf(format, $5,$6,$7)}" filename 

Ich habe mehrere { } -Blöcke zu einem zusammengefasst und auch die print-Anweisungen zu einem zusammengefasst.

Wenn ich Ihre awk-Anweisung von Grund auf neu schreiben würde, könnte ich Folgendes tun:

awk -v FS=\| -v OFS=, "{ $5=sprintf("%05.2f", $5); $6=sprintf("%05.2f", $6); $7=sprintf("%05.2f", $7); print $1,$2,$3,$4,$5,$6,$7}" filename 

Der Eingabefeldtrenner wird explizit festgelegt Der Ausgabefeldtrenner konvertiert jedes der Felder explizit für sich und druckt dann die gewünschten Felder, wobei das OFS sie trennt.

Kommentare

  • Wow !!! Das ist großartig und ich lerne viel. Schätzen Sie Ihre Zeit und Ihre informative Beschreibung wirklich 🙂 Am besten!

Antwort

Eine Möglichkeit, dies zu tun:

awk -F \| -v OFS=, "{ NF--; for(i = NF-2; i <= NF; i++) $i = sprintf("%07.2f", $i) } 1" filename 

Kommentare

  • @ Sato Katsura, Tnx viel funktioniert es perfekt. Darf ich Sie bitten, erklären Sie bitte Ihre Skripte, um es zu verstehen! Ich bin neu in Awk. Benötigen Sie nur die Erklärung für diesen Teil Ihres Skripts: {NF–; für (i = NF-2; i < = NF; i ++) $ i = sprintf ("% 07.2f ", $ i)} 1 '

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.