Sziasztok.
Adott egy söveges fie, melyben a sorokban vessző a mezőelválasztó (,).
Awk megmondja ugyan, hogy a 6. mezőnek milyen szám a tartalma, de kérdésem az,van-e az awk-nak olyan elvetemült kapcsolója, ami a BASH "sort -n" parancsát helyettesíti?
Azt szeretném, hogy a 6. oszlopban szereplő szám szerint csökkenő sorrendben íródjon ki a szöveges file tartalma.
Meg tudom oldani sok sorral a scriptet, de nem bírom elképzelni, hogy az awk ne tudna ilyesmit. A szöveges file közel 900 MB, sokat javítana a helyzeten, ha kisebb lenne a feldolgozó script.
Kösz minden tanácsot
- 2552 megtekintés
Hozzászólások
Nekem nem rémlik, hogy a Awk tudna ilyet (fix me). De:
sort -t, -nk6 fityfene.fie
- A hozzászóláshoz be kell jelentkezni
„csökkenő sorrendben”
Ezt csak most vettem észre. Akkor a sortnak kell egy „-r” opció is.
- A hozzászóláshoz be kell jelentkezni
kösz szépen, bejött :) ez volt ma nálam a nap csúcspontya'
- A hozzászóláshoz be kell jelentkezni
Én is azt mondanám a default awk nem tudja, de lehet ha van fent gawk vagy társai akkor azokban van valami sort funkció man alapján. (asort vagy mi man alapján)
- A hozzászóláshoz be kell jelentkezni
Itt van egy hasonló téma:
https://www.linuxquestions.org/questions/linux-general-1/how-to-use-awk…
A rendezéshez alapból benn kell tartani memóriában a rendezendő adatokat (vannak persze trükkös algoritmusok, amikhez nem kell az összeset benn tartani, de azok pláne nem elérhetőek awk-ban). Az awk meg ponthogy úgy működik, hogy olvassa a sorokat és egyből írja is a kimenetet. Tehát nem tartja benn a sorokat a memóriában. Az awk tehát alapból nem alkalmas a sorok rendezésére. (Nem vagyok awk guru, szóval akár tévedhetek is, de a linkelt topikban sincs tisztán awk-s megoldás.)
A sort-nak viszont van olyan paraméterezése, amivel tud x-edik oszlop szerint rendezni, és az elválasztót is be lehet állítani.
$ sort --help
...
-k, --key=KEYDEF sort via a key; KEYDEF gives location and type
...
-t, --field-separator=SEP use SEP instead of non-blank to blank transition
...
Arra kell vigyázni, hogy ha van escapelés a sorokban, akkor előfordulhat esetleg, hogy valahogy bonyolultabban kell feldolgozni a sorokat. Például CSV-ből ezerféle "szabvány" van, hogy hogy kell helyesen feldolgozni. De ha nincs szabadszöveges meződ, akkor könnyű dolgod van, és működik simán az elválasztók számlálása.
- A hozzászóláshoz be kell jelentkezni
+1
Ez a korrekt válasz, bár a C és a sort 6x gyorsabb.
- A hozzászóláshoz be kell jelentkezni
...sokat javítana a helyzeten, ha kisebb lenne a feldolgozó script.
Ezt hogy érted? ;)
Meg kell írni C-ben! Ahhoz nem kell egy sor script sem.
A bash nem rendelkezik sort paraccsal.
A 900MB nem egy méret manapság, bár ha a rekordszámról tudnák valamit...
A feldolgozó script a rendezésen kívül is csinálna valamit?
- A hozzászóláshoz be kell jelentkezni
Mondjuk a bash tudja használni a külső parancsokat, a sort pedig ilyen. Ráadásul azt hiszem, hogy az alap install készlet része. Így mindegy, milyen Shell fut, sort van.
- A hozzászóláshoz be kell jelentkezni
ami a BASH "sort -n" parancsát helyettesíti
Erre írtam.
- A hozzászóláshoz be kell jelentkezni
ha eeepc701-en kell feldolgoznod 2 GB rammal, 1 GB /dev/shm-mel, akkor az máááár nagy. 100 mb-okkal küzdök itt...
- A hozzászóláshoz be kell jelentkezni
Háát, elég szörnyűnek tűnik. ;)
Bár ezért tettem fel a kérdéseket.
Az a nagyszerű a klasszikus unix programokban, hogy nem kell nekik sok memória. Ezért aztán egy
awk | sort | awk
parancs (mivel egy pipeline == egy unix command) összesen 10MB körüli memóriát fogyaszt, miközben a feldolgozható adatmennyiség elméletileg korlátlan. Ráadásul a feldolgozás jobbára állandó sebességű, így a futásidő is kalkulálható.
A memóriába töltéshez viszont gondolkozni kell! Ha a rövid fejlesztési idő, de kicsit (kb. 6x) nagyobb futásidő kompromisszum megfelelő, érdemes használni az alap utility programokat.
- A hozzászóláshoz be kell jelentkezni
Csak pontosításképp írom, hogy a sort pipe-ban elvileg sem működhet 10MB memóriában. (A teljes adatsornak random access elérhetőnek kell lennie, a pipe-ban pedig ez nem teljesül.) Vagy RAM-ban, vagy valami tmp fájlban tárolnia kell a teljes adatsort.
(Lásd pl.: Donald Ervin Knuth: A számítógép-programozás művészete)
Ha az IO lassú, kevés a /tmp/, vagy nem elég a RAM, akkor ezek a dolgok számíthatnak.
- A hozzászóláshoz be kell jelentkezni
Mielőtt egy fórumon elkezdeném osztani az észt, először kipróbálom, esetleg még a man-t is megnézem. Én így csinálom, próbáld meg Te is, hátha bejön! ;)
PID %CPU Size Res Res Res Res Shared Faults Command
Used KB Set Text Data Lib KB Min Maj
1811 77.0 4108 648 56 264 0 560 0 0 od
1810 42.1 8336 648 48 272 0 532 0 0 dd
1813 32.8 9412 1792 88 1304 0 620 30 0 sort
1812 19.6 9084 864 348 288 0 708 0 0 awk
A fenti kimenetet az nmon-16d készítette. A parancs (opciók nélkül)
dd |od | awk |sort >file
Konkrétan 12800000 uint32 véletlen számot rendez.
a sort pipe-ban elvileg sem működhet 10MB memóriában
Szóval úgy véled, hogy a
sort file
sort <file
cat file|sort
parancsok esetén a sort más-más mennyiségű memóriát használ?
Miért is? :)
- A hozzászóláshoz be kell jelentkezni
Ehhez nem kell man, mert elvi probléma. Sort esetén addig nem kezdheted el írni a kimenetet, ameddig legalább egyszer végig nem olvastad az inputot. Bizonyítás: előfordulhat, hogy a bemenet utolsó eleme a legkisebb, amit a kimenetre először kell kiírnod. Na most, ha pipe-ban jön és pipe-ba megy az adat, akkor a kimenet első bájtjának írásakor a bemenetet már végigolvasta a processz, tehát az adatokat valahol tárolni kell, különben örökre elvesztek. A ki és bemenetet nem tudja tárolóként használni, tehát "saját magában" kell tárolnia az adatokat, ami praktikusan vagy memória, vagy tmp fájl.
Ha fájlból jön az input, akkor elvileg megteheti, hogy a bemeneti fájlt többször olvassa, ezért elvileg más feladat fájlban lévő adatokat rendezni, mint pipe-ból jövő adatokat. De a gyakorlatban értelmesen ezt nem lehet kihasználni ( O(n*n)-es algoritmussal lehetne csak kihasználni, az meg csigalassú lenne ), úgyhogy ez a felvetésem tényleg hülyeség.
Szerk.: itt van a doksi a paraméterhez, hogy mennyit tart "fejben" és mennyi után nyit tmp fájlokat, amikben rendez. Arra is utal a doksi, hogy valamiféle merge sortot csinál belül:
$ man sort
...
Other options:
--batch-size=NMERGE
merge at most NMERGE inputs at once; for more use temp files
...
- A hozzászóláshoz be kell jelentkezni
Ez mind szép, jó és igaz. Csak nem értem mit bizonygatsz ennyire bőszen. Csak annyit állítottam, hogy kis memóriafelhasználással lehetséges 2xawk+sort futtatása. Azzal is tisztában vagyok hogyan működik a sort. Sőt, azzal meg végképp, hogy unix alatt a legalapvetőbb process szinkronizálási módszer a pipe. A hozzászólást a topicnyitó problémájára írtam.
Sort esetén addig nem kezdheted el írni a kimenetet, ameddig legalább egyszer végig nem olvastad az inputot.
Ez triviális. De ennek sincs semmi köze a pipe-hoz.
...akkor a kimenet első bájtjának írásakor a bemenetet már végigolvasta a processz, tehát az adatokat valahol tárolni kell, különben örökre elvesztek.
Ez is igaz. Egyetlen problémát látok csak az eeepc esetén, ha az adatok nem férnek el több, mint kétszer. Ezt viszont több módon meg lehet kerülni, még pipe esetén is. (Ki mondta, hogy a pipe egyetlen egyenes csőszakasz? ;))
Az a MERGE, mint írja, az egyszerre feldolgozott tmp állományok darabszáma. Bár felfogható merge sort-ként is.
- A hozzászóláshoz be kell jelentkezni
Azért egészítettem ki először, mert félrevezetőnek találtam az "összesen 10MB körüli memóriát fogyaszt" kitételt. Kicsit úgy hangzott, mintha azt mondanám, hogy az elektromos autó ingyen megy, mert nem fogyaszt benzint. Valóban nem fogyaszt, de fogyaszt áramot. Ez meg nem fogyaszt RAM-ot, de fogyaszt diszkterületet.
- A hozzászóláshoz be kell jelentkezni
Annyiban igazad van, hogy a sort írja olvassa a teljes rekordot, amire nincs is szükség, hiszen a 6. numerikus mezőre kell rendezni.
Tételezzük fel, hogy
- ezek a sorok ügyfelek adatai és legalább 100 karakter hosszúak. Ekkor van 9M rekordunk.
- a rekord offset és a szám képezi az indexet, és egy index elem elfér 64 bitben.
- nem ragaszkodunk a script-hez.
Ekkor mmap-pel megnyitva az adatokat, be lehet gyűjteni a 72MB indexet. Ezt a memóriában rendezni, majd a kívánt sorrendben kiírni a sorokat pipe-ba további feldolgozásra. Ez minimum 5x gyorsabb a sort-nál, csak C-ben kell programozni. Viszont 0 diszk írás.
Minden bizonnyal a feldolgozáshoz szükséges többi program elfér 28MB-ban. Így a 900MB adat pont elfér a cache-ben, tehát az adatokat pontosan 1x kell beolvasni. No, meg 1x kiírni.
Ez már jobb?
- A hozzászóláshoz be kell jelentkezni
Köszönöm a gyors válaszokat, megindító volt.
A sort megoldotta a dolgot, az awk tényleg máshogy működik.
A fentieket a későbbiekben még nézegetem, a gawk még hátravan az életemből.
A probléma további része itt folytatódik, érdekességbe átcsapva:
https://hup.hu/node/156139
- A hozzászóláshoz be kell jelentkezni