awk formatera flyttal
awk formatera flyttal
Har en .csv-fil på följande format:
1234.123, namn, 23, 12.15
1301.123, namn2, 26, 29.5
Jag vill med awk massera datat till följande i en ny fil:
1234,123;namn;23;12,15
1301,123;namn2; 26;29,5
Jag lyckas inte konvertera flyttalens decimaltecken från ”.” till ”,”.
Sätta locale till svenska för ”,” som decimal separator får jag aldrig print eller printf i awk att skriva ut decimalerna efter ”,”.
Filerna är logg-filer som kan innehålla flera miljoner rader.
Testat under olika OS och dom uppför sig exakt lika i alla fall.
Någon med förslag på lösning?
1234.123, namn, 23, 12.15
1301.123, namn2, 26, 29.5
Jag vill med awk massera datat till följande i en ny fil:
1234,123;namn;23;12,15
1301,123;namn2; 26;29,5
Jag lyckas inte konvertera flyttalens decimaltecken från ”.” till ”,”.
Sätta locale till svenska för ”,” som decimal separator får jag aldrig print eller printf i awk att skriva ut decimalerna efter ”,”.
Filerna är logg-filer som kan innehålla flera miljoner rader.
Testat under olika OS och dom uppför sig exakt lika i alla fall.
Någon med förslag på lösning?
Re: awk formatera flyttal
Antar att du först byter kommatecknen till semikolon och först därefter punkterna till kommatecken, men hur ser dina kommandon ut?
Re: awk formatera flyttal
En variant som inte bryr sej om flyttal utan bara jobbar på tecken
Kod: Markera allt
echo '1234.123, namn, 23, 12.15'| awk 'BEGIN {FS=",";} {split($1,a,".");print a[1] "," a[2];}'
Re: awk formatera flyttal
Det var en smidig lösning!hawkan skrev: ↑15 december 2021, 21:42:43 En variant som inte bryr sej om flyttal utan bara jobbar på teckenKod: Markera allt
echo '1234.123, namn, 23, 12.15'| awk 'BEGIN {FS=",";} {split($1,a,".");print a[1] "," a[2];}'
Om jag vill göra det för flera tal ($1 och $2) på samma rad får jag inte till syntaxen.
Re: awk formatera flyttal
Om dina rader verkligen är så enkla att problemet är att byta komma mot semikolon och punkt mot komma kan man väl använda tr:
?
Kod: Markera allt
cat file | tr '.,' ',;'
Re: awk formatera flyttal
Jag vill även filtrera utfilen baserad på namn och adress (kolumn 2 och 3) för att förenkla arbetet med dom tvättade filerna.
Re: awk formatera flyttal
Med awk
med rör
Kod: Markera allt
echo '1234.123, namn, 23, 12.15'| gawk 'BEGIN {FS=",";} {split($1,a,".");split($4,b,".");print a[1] "," a[2] " " b[1] "," b[2];}'
Kod: Markera allt
tr '.,' ',;' | sort -t \; +2
Re: awk formatera flyttal
Jag hade också använt tr, det beror mest på att awk är synnerligen komplicerat, om än extremt kompetent.
Det finns folk som kan "prata awk flytande", jag minns när jag hade nåt riktigt komplicerat problem och försökte med nästlade cut, grep och tr och fick
inte riktigt till det, beklagade mej till en kompis som är wizard på awk, som på typ en minut kom fram till en lång awk-rad som gjorde EXAKT det jag ville göra - på första försöket.
Även sed löser säkert problemet, men är också komplicerat att lära sej.
(min awkbok är på över 1000 sidor vill jag minnas..)
Det finns folk som kan "prata awk flytande", jag minns när jag hade nåt riktigt komplicerat problem och försökte med nästlade cut, grep och tr och fick
inte riktigt till det, beklagade mej till en kompis som är wizard på awk, som på typ en minut kom fram till en lång awk-rad som gjorde EXAKT det jag ville göra - på första försöket.
Även sed löser säkert problemet, men är också komplicerat att lära sej.
(min awkbok är på över 1000 sidor vill jag minnas..)
Re: awk formatera flyttal
För att komlicerad ytterilgare:
Jag gillar Perl för sånt här.
AWK , sed och tr i all ära, men Perl har en renare syntax och lämpar sig bättre för längre program.
Och mer kompetent. Ett skal på stereoider.
Men det är kanske en smaksak.
Exempel:
echo "1234.123, namn, 23, 12.15" | perl -e 'foreach (<>) { tr /.,/,:/; print $_; }'
Jag gillar Perl för sånt här.
AWK , sed och tr i all ära, men Perl har en renare syntax och lämpar sig bättre för längre program.
Och mer kompetent. Ett skal på stereoider.
Men det är kanske en smaksak.
Exempel:
echo "1234.123, namn, 23, 12.15" | perl -e 'foreach (<>) { tr /.,/,:/; print $_; }'
Re: awk formatera flyttal
Varför ska awk användas till det här, det är ett regex-problem som kan lösas med sed:
Eller i Perl vilket jag också föredrar, men det här problemet var så trivialt att även den primitiva regex-motorn i sed klarar av det:
Notera att jag tar höjd för att mellanslag kan finnas på vardera sida av semikolonen.
Om det är så att semikolon redan kan finnas i posterna eller att mellanslag kan finnas mitt i posterna, då kan man dela upp CSV-raderna på kommatecknet först så att man sedan kan behandla varje post individuellt:
Kod: Markera allt
$ echo 1234.123, namn, 23, 12.15 | sed 'y/,/;/;y/./,/;s/ *; */;/g'
1234,123;namn;23;12,15
Kod: Markera allt
$ echo 1234.123, namn, 23, 12.15 | perl -wpe 'y/,/;/;y/./,/;s/ *; */;/g'
1234,123;namn;23;12,15
Om det är så att semikolon redan kan finnas i posterna eller att mellanslag kan finnas mitt i posterna, då kan man dela upp CSV-raderna på kommatecknet först så att man sedan kan behandla varje post individuellt:
Kod: Markera allt
$ echo 1234.123, namn, 23, 12.15 | perl -wnle 'for(split ","){s/^ +//;y/./,/;s/ +$//;push @_,$_};print join ";",@_'
1234,123;namn;23;12,15
Re: awk formatera flyttal
Du har nog rätt i att jag kanske använder fel verktyg.
Som jag nämnde ovan men tyvärr inte skrev i första inlägget, vill även filtrera data från filen baserad på namn och adress (kolumn 2 och 3). Det kommer genereras ett 50-tal filer beroende på kolumn 2 och 3. Kan du knuffa mig i rätt riktning för att göra det urvalet med hjälp av något av dina förslag?
Som jag nämnde ovan men tyvärr inte skrev i första inlägget, vill även filtrera data från filen baserad på namn och adress (kolumn 2 och 3). Det kommer genereras ett 50-tal filer beroende på kolumn 2 och 3. Kan du knuffa mig i rätt riktning för att göra det urvalet med hjälp av något av dina förslag?
Re: awk formatera flyttal
Fel och fel, det finns många sätt att flå en katt på.
För att sortera på andra posten, gör som Hawkan föreslog:
Några följdfrågor:
Är det Linux du jobbar i, eller är det bara ett antagande eftersom du frågade om hjälp med awk?
Är det svenska tecken i CSV-filerna?
Är filerna UTF8?
Finns det Byte Order Mark i filerna?
För att sortera på andra posten, gör som Hawkan föreslog:
Kod: Markera allt
$ cat infil.csv
1234.121, namn9, 23, 12.15
1234.122, namn8, 23, 12.15
1234.123, namn7, 23, 12.15
1234.124, namn6, 23, 12.15
1234.125, namn5, 23, 12.15
1234.126, namn4, 23, 12.15
1234.127, namn3, 23, 12.15
1234.128, namn2, 23, 12.15
1234.129, namn1, 23, 12.15
$ cat infil.csv | sed 'y/,/;/;y/./,/;s/ *; */;/g' | sort -t \; -k2
1234,129;namn1;23;12,15
1234,128;namn2;23;12,15
1234,127;namn3;23;12,15
1234,126;namn4;23;12,15
1234,125;namn5;23;12,15
1234,124;namn6;23;12,15
1234,123;namn7;23;12,15
1234,122;namn8;23;12,15
1234,121;namn9;23;12,15
Är det Linux du jobbar i, eller är det bara ett antagande eftersom du frågade om hjälp med awk?
Är det svenska tecken i CSV-filerna?
Är filerna UTF8?
Finns det Byte Order Mark i filerna?
Re: awk formatera flyttal
Det är linux och macOS som det kommer köras på.
Ger ditt förslag en egen fil för varje sortering på dom 2 kolumnerna?
Nej inga svenska tecken, 8 bitar per tecken. BOM används inte.
Ger ditt förslag en egen fil för varje sortering på dom 2 kolumnerna?
Nej inga svenska tecken, 8 bitar per tecken. BOM används inte.