Mam następujący plik:
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|
Próbuję sformatować ten plik używając awk printf, aby mieć następujący pożądany format:
- zachowaj tę samą kolejność pól (lewo -> prawo)
- przecinek „,” FS
- tylko dla l trzech pól (5 USD, 6 USD, 7 USD) , w których wszystkie liczby mają 4 cyfry, jeśli mniej ma początkowe zero i tylko 2 cyfry po przecinku, jak 0123.12 lub 1234.10
Napisałem następujące polecenie awk
awk -F"|" "{print $1","$2","$3","$4}{format = "%04.2f,%04.2f,%04.2f,"}{printf format, $5,$6,$7}" filename
jednak poniższe dane wyjściowe mają następujące problemy:
-
nie jest w porządku (od lewej do prawej)
-
nie mają początkowego zera
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
Czy ktoś może mi powiedzieć, jaki jest mój błąd i jak go naprawić?
Komentarze
– ale to nie ' nie odpowiada na twoje szersze pytanie.
Odpowiedź
Masz pola we właściwej kolejności, ale pierwsza instrukcja print dodaje nowy wiersz (separator rekordów wyjściowych), więc dane są tam, ale po prostu nieoczekiwanie zawijane.
Drugą kwestią jest to, że mówisz printf, aby używał szerokości 4; który zawiera przecinek dziesiętny i dwie cyfry po nim, pozostawiając tylko jedną cyfrę wiodącą i żadną dla wypełnienia. Spróbuj użyć 5 jako szerokości, aby dane były uzupełnione do czterech liczb łącznie. Jeśli chcesz mieć 4 cyfry przed kropką dziesiętną, zamiast tego zmień szerokość na 7.
To jest najkrótsza zmiana, jaką wprowadziłem w twoim programie na coś, co wyświetla to, co myślę chcesz:
awk -F"|" "{ format = "%05.2f,%05.2f,%05.2f"; print $1","$2","$3","$4"," sprintf(format, $5,$6,$7)}" filename
Połączyłem wiele bloków { }
w jeden, a także połączyłem instrukcje print w jeden.
Gdybym miał napisać twoją instrukcję awk od zera, mógłbym zrobić coś takiego:
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
To jawnie ustawia separator pól wejściowych , Separator pól wyjściowych, jawnie konwertuje każde z pól na własną rękę, a następnie drukuje żądane pola, oddzielając je OFS.
Komentarze
- Wow !!! To jest świetne i dużo się uczę. Naprawdę doceniam poświęcony czas i pouczający opis 🙂 Najlepsze!
Odpowiedź
Można to zrobić w jeden sposób:
awk -F \| -v OFS=, "{ NF--; for(i = NF-2; i <= NF; i++) $i = sprintf("%07.2f", $i) } 1" filename
Komentarze
- @ Sato Katsura, Tnx dużo działa doskonale. Czy mogę prosić o wyjaśnienie naszym skryptom, aby to zrozumieć! Jestem nowy w Awk. Potrzeba tylko wyjaśnienia dla tej części skryptu: {NF–; for (i = NF-2; i < = NF; i ++) $ i = sprintf ("% 07.2f ", $ i)} 1 '
'BEGIN {OFS=","}'
lub po prostu