Sziasztok!
Szeretnék írni egy scriptet amiben a havi telefonszámlám van nekem megfelelően részletezve. Vagyis szolgáltatónként a fizetendő összeg, és az összes összeg, valamint ugyan így a beszélt idők, SMS-ek száma is. Pénz összegekkel pont meg is tudtam írni egy sorban gawk segítségével:
gawk '{FS=";"}
{sum += 8}
/Vodafone/ {v += $8}
/Telenor/ {p += $8}
/T-Mobile/ {t += $8}
/Budapest/ {b += $8}
END {print sum}
END {print t,p,v,b}
END {print t+p+v+b}'
A vodafonetól letöltött .csv fájl így kiad 3 sort:
A teljes oszlop összege
Az általam beállított szolgáltatók összege
Szolgáltatók összeadva (ez csak azért kell mert hátha van még valami külföld, egyéb szolgáltató mit tudom én, szóval az első és 3. sornak egyeznie kell)
De mit csináljak a 'Időtartammal'? Ahol hh:mm:ss formátumban vannak az adatok vagy kB-ban az adatforgalom. Hogy lehet összeadni időket awk segítségével? Van rá lehetőség?
- 6969 megtekintés
Hozzászólások
A kB-ot az idővel összeadni nem érdemes. :-)
Az idők összeadására (és kívonására) kb. 15 évvel ezelőtt írtam függvényeket, és azt használtam. Azóta nem használtam, így nem tudom megígérni, hogy gyorsan megtalálom. De egyszerű a dolog: átalakítod az időket másodpercekre, majd összeadod, és az eredményt visszaalakítod „normál” formátumra.
-----
A kockás zakók és a mellészabások tekintetében kérdezze meg úri szabóját.
- A hozzászóláshoz be kell jelentkezni
Valami ilyesmire kell gondolni:
awk '{split($1, t, ":"); sum+=3600*t[1]+60*t[2]+t[3]} END { print strftime("%H:%M:%S", sum-3600)}' times.txt
kB adatok eldobás:
awk '{split($1, t, ":"); if ($1!=t[1]) sum+=3600*t[1]+60*t[2]+t[3]} END { print strftime("%H:%M:%S", sum-3600)}' times.txt
-----
A kockás zakók és a mellészabások tekintetében kérdezze meg úri szabóját.
- A hozzászóláshoz be kell jelentkezni
Mi az a -3600?
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Az „időszámítás” kezdete nem 00:00:00, hanem 01:00:00.
-----
A kockás zakók és a mellészabások tekintetében kérdezze meg úri szabóját.
- A hozzászóláshoz be kell jelentkezni
Pláne nem értem. Egyrészt miért, másrészt mivel összeadjuk az időket, nem időtartamokról van szó?
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Az összeadással nincs baj. A „baj” azzal van, hogy a strftime timestampet vár. Próbáld ki:
echo "" | awk 'END {print(strftime("%H:%M:%S", 0))}'
Ugyan nem íratjuk ki teljesen, de 1970. 01. 01. 01:00:00-t jelent a 0-s timestamp.
-----
A kockás zakók és a mellészabások tekintetében kérdezze meg úri szabóját.
- A hozzászóláshoz be kell jelentkezni
Szerintem meg nem. Az a szörnyű érzésem támadt, hogy az időzónát korrigáltad így. Vagy a nyári időt. Valami azt súgja, ez a -3600 nem fog stimmelni télen. Lehet, mindent UTC-ben kellene számolni.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Amikor az írtam, hogy az időszámítás 01:00:00-val kezdődik, abban benne volt, hogy mi a CET időzónában vagyunk. Valóban helyesebb lett volna azt írni, hogy a mi időzónánkban kezdődik 1 órától az időszámítás.
Ha a nyári/téli időszámítás probléma lenne, akkor most 2 órát kellene levonni a helyes értékhez.
Azt is elismerem, hogy korrektebb lenne, ha az strftime függvénnyel előbb lekérdezném az időzónát (%z, %Z), és ez alapján végezném el a korrekciót. Azonban az eredeti feladatból kiindulva, viszonylag kevesen lehetnek, akik egy másik időzónában akarják feldolgozni a magyar szolgáltatótól kapott számla adatait.
Kieg.:
awk '{split($1, t, ":"); if ($1!=t[1]) sum+=3600*t[1]+60*t[2]+t[3]} END { tz=strftime("%z", 0); print strftime("%H:%M:%S", sum-36*tz)}' times.txt
-----
A kockás zakók és a mellészabások tekintetében kérdezze meg úri szabóját.
- A hozzászóláshoz be kell jelentkezni
Az időzóna ilyen kézi manipulálását nem szeretem. Volt, hogy én is így generáltam egy scriptemben listát, s egy egész nap eltűnt a listából a téli-nyári átállás környékén. Ez úgy jött ki, hogy 23 órás lett a nap, azt elosztottam 24-gyel, amelynek az egészrésze 0 lett, így tehát szépen eltűnt egy teljes napom.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Sztem a bérjellegű kifizetések minimalizálásában érdekelt HR-eseknek tetszene ilyen fícsör a bérszámfejtésben.
Nincs az a selejt, ami valahol még ne volna használható.
- A hozzászóláshoz be kell jelentkezni
LOL :D
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Ez sem jó, mert ahol fél óra az időeltérés, ott bukik ez a 36-tal szorzás. Mondjuk ilyen -0530 vagy efféle esetben.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Sőt ott sem jó, ahol 45 perces az időeltérés. Tehát Nepálban sem fog működni. Tehát az irániak és a nepáliak is jól megszívták. :-)
-----
A kockás zakók és a mellészabások tekintetében kérdezze meg úri szabóját.
- A hozzászóláshoz be kell jelentkezni
Na jó, de ennyire azért illik általánosan megírni egy scriptet, nem?
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
> tz=strftime("%z", 0); print strftime("%H:%M:%S", sum-36*tz)
Ez a kivonogatas sok galibat okozhat.
Sokkal inkabb:
TZ=UTC awk '{.... }'
es nem kell idozonakkal foglalkozni. Sajat peldad:
echo "" | gawk 'END {print(strftime("%H:%M:%S", 0))}'
01:00:00
viszont:
echo "" | TZ=UTC gawk 'END {print(strftime("%H:%M:%S", 0))}'
00:00:00
- A hozzászóláshoz be kell jelentkezni
+1
- A hozzászóláshoz be kell jelentkezni
Ez tényleg egyszerűbb és sokkal jobb megoldás. Sokszor a túl egyszerű megoldások nem jutnak eszünkbe.
-----
A kockás zakók és a mellészabások tekintetében kérdezze meg úri szabóját.
- A hozzászóláshoz be kell jelentkezni
Ez az echo | awk oly ronda :-) . A BEGIN mintában szereplő dolgokat még /dev/null feldolgozása esetén is végrehajtja az awk:
TZ=UTC gawk 'BEGIN {print strftime("%H:%M:%S", 0) ; }' /dev/null
pont ugyanilyen jó, csak olcsóbb ;-)
(Amúgy az igazán szép az lenne, ha nem kívülről kellene az időzónát piszkálni, de sajnos hiába állítom át az awk-n belülről, nem hajlandó kezelni:
gawk 'BEGIN { ENVIRON["TZ"]="UTC" ; print strftime("%H:%M:%S", 0) ; }' /dev/null
Sőt a gawk és a mawk manuáljában szerepel is - igaz, csak a system-re és a pipe-pal indítot proccesszekre térnek ki, de ettől függetlenül nem működik.)
Ja, mondjuk pont az strftime éppen gawk-only, és mint olyan, nem hordozható.
- A hozzászóláshoz be kell jelentkezni
Kipróbáltam, a BEGIN blokkot akkor is lefuttatja, ha nincs input. Ezzel szemben az END blokk futásához kellett legalább a /dev/null feldolgozásra.
GNU Awk 4.0.2
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Nézegetem, finomítgatom egyenlőre még elég nagy időt ad meg (percben), nem hiszem hogy olyan sokat beszéltem.
- A hozzászóláshoz be kell jelentkezni
Ez működik:
awk -F";"
'/Telenor/
{n=split($6,a,":");
if ($6!=a[1])
s+=(a[1]*3600+a[2]*60+a[3])} END
{printf("%02d:%02d:%02d\n", s/3600,s%3600/60,s%3600%60)}' file.csv
- A hozzászóláshoz be kell jelentkezni
Számold át másodpercbe, add össze, majd konvertáld vissza óra, perc, másodpercre. Nem tűnik bonyolultnak.
A kB, MB, s effélékre is tudsz táblázatot csinálni, amelyben a szorzó 1024, 1048576 és effélék. Vagy 1000, 1000000. Nem tudom, itt binárisan, vagy SI szerint decimálisan értendő.
Némileg átláthatóbb lenne, ha az awk scriptet nem egy sorba írnád.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Haha, megelőzöm Zahyt: DEHÁT A GAWK NEM IS HORDOZHATÓ!!!!11 :D
miért ragaszkodsz a gawkhoz? mi olyan feature van benne, amit itt használnod _KELL_? az időkkel való zsonglőrködés úgy a leghatásosabb, ha unix timestamppá alakítod őket. sajnos nem vicc.
kilo/mega/gigabájtok konvertálása pedig könnyedén megtanulható mondjuk a 'df' vagy a 'du' forráskódjának tanulmányozásával.
- A hozzászóláshoz be kell jelentkezni
Akkor mit kéne használni, simán awk?
- A hozzászóláshoz be kell jelentkezni
perl-ben str2time -t ajánlom.
- A hozzászóláshoz be kell jelentkezni
python :)
- A hozzászóláshoz be kell jelentkezni
Pythonban merre induljak?
Hogyan dolgozzam fel a .csv fájlokat?
- A hozzászóláshoz be kell jelentkezni
----
"Kb. egy hónapja elkezdtem írni egy Coelho-emulátort, ami kattintásra generál random Coelho-kompatibilis tartalmat."
Instant Coelho
- A hozzászóláshoz be kell jelentkezni
Pontosan. Erre a feladatra bőven elég a "sima" (n)awk. Első ránézésre semmi olyat nem használsz ki, amit akár az (old) awk ne tudna.
Két megjegyzés:
Szerintem a legelső részben nem 8-at, hanem $8-at akarsz a sum-hoz adni.
A második, hogy az END { A ; } END { B; } END { C; } abszolut nem szabványos, de legalább nincs is rá szükség, simán lehet egy db END mintában több utasítás END { A; B; C; } formában.
(Csak azért kötözködök, mert az összes többit már gyakorlatilag megválaszolták :-) )
- A hozzászóláshoz be kell jelentkezni
Tök jól megy, már majdnem megvan minden amit akartam, csak még problémás, hogy egyik oszlopban megtalálható a 'Vodafone' és a 'Vodafone Internet' is. Na most nekem minden olyan sor kéne amiben a 'Vodafone' szerepel. Amit próbáltam és nem megy:
awk -F=';' '/\/ {print}' 0507599656.csv
awk -F=';' '/^Vodafone$/ {print}' 0507599656.csv
gawk -F=";" '$3 == /Vodafone/ {print}' 0507599656.csv
gawk -F=";" '($3 == "Vodafone") {print NR}' 0507599656.csv
Ez persze szépen lefut...
awk -F=';' '/Vodafone\ Internet/ {print}' 0507599656.csv
- A hozzászóláshoz be kell jelentkezni
awk '/Vodafone/' 0507599656.csv
Vagy mit nézek be?
- A hozzászóláshoz be kell jelentkezni
Találtam egy működő megoldást:
awk -F\; '$3 == "Vodafone" {print}' 0507599656.csv
Mivel a ';' küönleges karakter, kell elé a '\' jel hogy sima karakterként legyen értelmezve.
awk '{FS=";"} $3 == "Vodafone" {print}' 0507599656.csv
ez ugyan azt csinálja mint a fenti.
De egy /^Vodafone$/
formát sehogy sem tudok működésre bírni. A sima /Vodafone/
pedig minden olyan sort listáz, amiben szerepel a Vodefone, tehát a Vodefone Internet tartalmú sorokat is.
- A hozzászóláshoz be kell jelentkezni
"De egy /^Vodafone$/ formát sehogy sem tudok működésre bírni."
Mondd, rászántál egy órát arra, hogy elolvasd az awk-programok végrehajtásának menetét? Itt elsősorban a mezőkre bontás és mintaillesztés részekre gondolok?
Másképp kérdezve: tudod, hogy mi a mező, és hogy mire próbál illeszkedni egy konstans reguláris kifejezés, ha nem adod meg konkrétan, hogy mire illeszkedjen?
Hint: illesszünk mintát az n. mezőre, ne az egész bemeneti rekordra!
- A hozzászóláshoz be kell jelentkezni
Elvesztem, hogy ma éppen mi a feladat. Leírnád még egyszer? (Megjegyzések:
- azt írtad, hogy need minden olyan sor kell, amiben a Vodafone bennevan. Mivel a Vodafone Internetet tartalmazó sorban is benne van, szerntem evidens, hogy azt is megtaláklod. Lehet, hogy fenti leírásoddal ellentétben azokat a sorokat nem akarod kiíratni?
- tudom, hogy miért takarod el a ; -t, ez nem gond.
- cserébe nem tudom miért rakod oda a mintáéhoz a { print } részt. Ha nincs AKCIÓ egy awk MINTA mellett, ez az alapértelmezés, tehát simán kihagyhatod.)
Mit szólsz ehhez?
awk '$0 ~ /Vodafone/ && $0 !~ /Vodafone internet/' izemize.ecet.csv
Persze ha mániád hogy mezőkre tördeled a ; mentén, meg hogy csak a 3. mezőben érdekel, akkor ki lehet egészíteni azokkal is.
- A hozzászóláshoz be kell jelentkezni