awk formatera flyttal

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
hummel
Inlägg: 2267
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

awk formatera flyttal

Inlägg av hummel »

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?
Användarvisningsbild
rvl
Inlägg: 5772
Blev medlem: 5 april 2016, 14:58:53
Ort: Helsingfors

Re: awk formatera flyttal

Inlägg av rvl »

Antar att du först byter kommatecknen till semikolon och först därefter punkterna till kommatecken, men hur ser dina kommandon ut?
Användarvisningsbild
hawkan
Inlägg: 2618
Blev medlem: 14 augusti 2011, 10:27:40

Re: awk formatera flyttal

Inlägg av hawkan »

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];}'
hummel
Inlägg: 2267
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: awk formatera flyttal

Inlägg av hummel »

rvl skrev: 15 december 2021, 21:36:04 Antar att du först byter kommatecknen till semikolon och först därefter punkterna till kommatecken, men hur ser dina kommandon ut?
läser in "." från infil och skriver "," till utfil är min försök.
LC_NUMERIC="sv_SE.UTF-8" awk '{printf "%f;%s\n", $1, $2}' $1
hummel
Inlägg: 2267
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: awk formatera flyttal

Inlägg av hummel »

hawkan skrev: 15 december 2021, 21:42:43 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];}'
Det var en smidig lösning!
Om jag vill göra det för flera tal ($1 och $2) på samma rad får jag inte till syntaxen.
guckrum
Inlägg: 1683
Blev medlem: 19 juni 2012, 09:04:27
Ort: Lund

Re: awk formatera flyttal

Inlägg av guckrum »

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 '.,' ',;'
?
hummel
Inlägg: 2267
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: awk formatera flyttal

Inlägg av hummel »

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.
guckrum
Inlägg: 1683
Blev medlem: 19 juni 2012, 09:04:27
Ort: Lund

Re: awk formatera flyttal

Inlägg av guckrum »

Då är väl grep nästa program i pipen?
Användarvisningsbild
hawkan
Inlägg: 2618
Blev medlem: 14 augusti 2011, 10:27:40

Re: awk formatera flyttal

Inlägg av hawkan »

Med awk

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];}'
med rör

Kod: Markera allt

tr '.,' ',;' | sort -t \; +2
Användarvisningsbild
Glenn
Inlägg: 33747
Blev medlem: 24 februari 2006, 12:01:56
Ort: Norr om Sthlm
Kontakt:

Re: awk formatera flyttal

Inlägg av Glenn »

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..)
SvenW
Inlägg: 1122
Blev medlem: 24 april 2007, 16:23:10
Ort: Göteborg

Re: awk formatera flyttal

Inlägg av SvenW »

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 $_; }'
Maalobs
Inlägg: 1299
Blev medlem: 3 februari 2005, 14:35:15
Ort: Stockholm

Re: awk formatera flyttal

Inlägg av Maalobs »

Varför ska awk användas till det här, det är ett regex-problem som kan lösas med sed:

Kod: Markera allt

$ echo 1234.123, namn, 23, 12.15 | sed 'y/,/;/;y/./,/;s/ *; */;/g'
1234,123;namn;23;12,15
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:

Kod: Markera allt

$ echo 1234.123, namn, 23, 12.15 | perl -wpe 'y/,/;/;y/./,/;s/ *; */;/g'
1234,123;namn;23;12,15
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 | perl -wnle 'for(split ","){s/^ +//;y/./,/;s/ +$//;push @_,$_};print join ";",@_'
1234,123;namn;23;12,15
hummel
Inlägg: 2267
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: awk formatera flyttal

Inlägg av hummel »

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?
Maalobs
Inlägg: 1299
Blev medlem: 3 februari 2005, 14:35:15
Ort: Stockholm

Re: awk formatera flyttal

Inlägg av Maalobs »

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:

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
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?
hummel
Inlägg: 2267
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: awk formatera flyttal

Inlägg av hummel »

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.
Skriv svar