Hogyan rendezhetem egy Linuxos awk szkripten belül?

Van egy fruit fájlom, amely a következő tartalommal rendelkezik:

Apples, 12 Pears, 50 Cheries, 7 Strawberries, 36 Oranges, 2 

Szeretném rendezni a fájl numerikus adatait:

for(i=1;i<=NF;i++)j+=$i;printf "Fruit %d%s, %d\n",NR,OFS,$1,j | sort -k 2 > "numbers"; j=0" 

Az awk parancsfájl futtatásához futtatom a parancsot :

awk -f numbers fruit 

A számfájl tartalma megegyezik a gyümölcsével, de az 1. és 2. mezőjét átmásolja a számfájlba.

Megjegyzések

  • Miért kell az awk-ban válogatni? Awk nem rendelkezik ‘ nem natív rendezési képességekkel, miért nem ‘ miért csak rendezi a kimenetet?
  • @ A terdon GNU awk (ami szerintem az alapértelmezett awk a Linuxon) rendelkezik natív rendezési képességekkel.
  • @EdMorton lásd az utolsó kérdésüket valamilyen kontextus. És ‘ teljesen igazad van! A GNU awk asort. Esküdhettem volna rá, hogy valamiért nem ‘ t. Köszönöm! Nem egészen biztos, hogy megéri-e, mivel ‘ be kell olvasnod a teljes fájlt tömbbe, majd rendezni a tömböt, így a kimenet rendezése valószínűleg még hatékonyabb lenne, de ‘ ehhez több mint elegendő.
  • @terdon Nem csak ‘ van asort() sokkal hasznosabb sorted_in is van, hogy egyszerűen meghatározhasson egy sorrendet a for (i in array) számára keresse fel a tömb elemeit – lásd: gnu.org/software/gawk/manual/gawk.html#Controlling-Scanning.I egyetértek abban, hogy pusztán a UNIX rendezéshez való csővezetés hatékonyabb ennél a problémánál.
  • @EdMorton A GNU awk NEM az alapértelmezett a debianban és hasonlókban. ” mawk ” az alapértelmezett, amelynek ‘ nincs ” asort ” beépített függvény.

Válasz

A GNU awk segítségével könnyedén szabályozhatja, hogyan haladjon át egy tömbön: lásd: A tömb átjárásának vezérlése és Szkennelés ellenőrzése

gawk -F", " " {fruit[$1] = $2} END { OFS = FS printf "\nordered by fruit name\n" PROCINFO["sorted_in"] = "@ind_str_asc" for (f in fruit) print f, fruit[f] printf "\nordered by number\n" PROCINFO["sorted_in"] = "@val_num_desc" for (f in fruit) print f, fruit[f] } " fruit 

kimenetek

ordered by fruit name Apples, 12 Cheries, 7 Oranges, 2 Pears, 50 Strawberries, 36 ordered by number Pears, 50 Strawberries, 36 Apples, 12 Cheries, 7 Oranges, 2 

Válasz

Az awk “s print valóban átadható a "sort" (vegye figyelembe az idézőjeleket):

$ awk "{print "Fruit",NR, $0 | "sort -k 2 -t, -rn"}" fruit Fruit 2 Pears, 50 Fruit 4 Strawberries, 36 Fruit 1 Apples, 12 Fruit 3 Cheries, 7 Fruit 5 Oranges, 2 

Tehát a numbers címre írva megteheti:

awk "{print "Fruit",NR, $0 | "sort -k 2 -t, -rn > numbers"}" fruit 

Ne feledje, hogy kissé leegyszerűsítettem az awk-ját. Nem szükséges itt használni a printf -et, vagy kifejezetten nyomtatni OFS mivel nem változtatsz sehol. I al tehát ne lássa, mit csinál a for(i=1;i<=NF;i++)j+=$i. Már megvan a (z) NR kód, és printf a “div div = = 6f0ac34b8d”>

használatával nem volt “t”.

Megjegyzések

  • Ahelyett, hogy rendezést hívna az awk-ben, ‘ egyszerűbb és hatékonyabb az egyszerű nyomtatás az awk-ben és pipázza az awk-kimenetet a rendezéshez: awk '{print ...}' fruit | sort ....
  • @EdMorton ó, abszolút! Magam soha nem használnám ezt a megközelítést, mi ‘ s a lényeg? De ezt kérte az OP .
  • Gyakran találok követelményt a rendezésre a gawk-on belül, amikor nem akarom ‘ rendezni a teljes kimenetet. Például statisztikákat gyűjtök és jelentek minden bemeneti fájl esetében. Használhatok díszítés / rendezés / klip módszert a készítsen egyszerű kulcsokat összetett adatokból (pl. rangsorolja az elektromos berendezések túlterhelését a maximális besorolású oldalsó tömb felhasználásával). A külső rendezéshez lemezes munkafájlokat és split / merge stratégiát is használnak. a rendezés jobb módszereket is alkalmazhat.
  • @JoeSkora nem kell ‘ nem kell egy alhéjat létrehoznia az awk-ból, majd remélni, hogy az összes érintett pufferelés a kimenethez vezet attól kezdve, hogy az alhéj az awk parancs kimenetének többi része után az stdout-ba kerül, ahelyett, hogy előtte vagy adott esetben a közepén lenne. Csak tegye awk '{print (NR>1), $0}' | sort -k1,1n -k2 | cut -d' ' -f2-
  • @EdMorton Szeretem kinyomtatni a feltételes, nagyszerű ötletet. Az utolsó rész tovább egyszerűsíthető, ezt hagyva. awk '{print (NR>1),$0}' | sort ... | cut -c3-.

Válasz

Biztosan komoly Probléma volt a SunOS nawk-val 2002-ben. Megtaláltam a teszt szkriptemet, amely három awk-implementációt tartalmazott, amelyek a nem GNU awk-n belül futnak:

(a) eSort: egy munkafájlt használ, és visszaolvas egy csövön futó sort parancsot. Az én esetemben nem jó, mert az ssh-n keresztül dolgoztam ügynökök nélküli megfigyelés céljából, és a külső munkafájlok túl invazívak voltak az élő szervereink számára.

(b) qSort: rekurzív partíciós rendezés. A teljesítmény nagy adatok esetén rossz, és több mint 2000 elem esetén megszakítja a mawk veremét. Szórakoztató írni.

(c) hSort: egy sort-in-in-algoritmus 15 sorban. Ez a halom indexelő algoritmust használ egy bináris fa támogatására (lásd: Wikipédia).

Ez a bash szkript a hSort és a hUp awk függvényeket tartalmazza, amelyek megvalósítják a tényleges rendezést. Az egyik műveletsor az összes bemenetet egy tömbbe helyezi, és az END blokk meghívja a hSort rendszert és jelentést készít az eredményekről.

A bemeneti adatok a “man bash” tartalma, egyszer sorokként, ismét szavakként. A wc-t használjuk annak bizonyítására, hogy semmi sem veszett el, és a -c rendezéssel igazoljuk, hogy a kimenet rendezve van. Az időzítés tartalmazza az olvasás és a nyomtatás általános költségeit.

Ez a tesztlövés:

Paul--) ./hSort Sorted 5251 elements. real 0m0.120s user 0m0.116s sys 0m0.004s 5251 44463 273728 hSort.raw sort: hSort.raw:2: disorder: 5251 44463 273728 hSort.srt Sorted 44463 elements. real 0m1.336s user 0m1.316s sys 0m0.008s 44463 44463 265333 hSort.raw sort: hSort.raw:3: disorder: Commands 44463 44463 265333 hSort.srt 

Ez a szkript. Élvezze!

#! /bin/bash export LC_ALL="C" #### Heapsort algorithm. function hSort { #:: (void) < text local AWK=""" #.. Construct the heap, then unfold it. function hSort (A, Local, n, j, e) { for (j in A) ++n; for (j = int (n / 2); j > 0; --j) hUp( j, A[j], n, A); for (j = n; j > 1; --j) { e = A[j]; A[j] = A[1]; hUp( 1, e, j - 1, A); } return (0 + n); } #.. Given an empty slot and its contents, pull any bigger elements up the tree. function hUp (j, e, n, V, Local, k) { while ((k = j + j) <= n) { if (k + 1 <= n && STX V[k] < STX V[k + 1]) ++k; if (STX e >= STX V[k]) break; V[j] = V[k]; j = k; } V[j] = e; } { U[++nU] = $0; } END { sz = hSort( U); printf ("\nSorted %s elements.\n", sz) | "cat 1>&2"; for (k = 1; k in U; ++k) print U[k]; } """ mawk -f <( printf "%s\n" "${AWK}" ) } #### Test Package Starts Here. function Test { time hSort < hSort.raw > hSort.srt for fn in hSort.{raw,srt}; do wc "${fn}"; LC_ALL="C" sort -c "${fn}"; done } AWK_LINE="{ sub (/^[ \011]+/, ""); print; }" AWK_WORD="{ for (f = 1; f <= NF; ++f) print $(f); }" #xxx : > hSort.raw; Test #.. Edge cases. #xxx echo "Hello" > hSort.raw; Test #xxx { echo "World"; echo "Hello"; } > hSort.raw; Test man bash | col -b | mawk "${AWK_LINE}" > hSort.raw; Test man bash | col -b | mawk "${AWK_WORD}" > hSort.raw; Test 

Válasz

A HeapSort szabványos awk-ban kevesebbel írható mint 20 sor. Nem vakítóan gyorsan, de ésszerűen megfelel a nyelvnek.

Megjegyzések

  • Ó, nem tettem ‘ t küldd el. Kijelentettem a létezését, és gyakorlatként hagytam az olvasó számára.
  • A kódot és a tesztet 2020. január 9-én tették közzé

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük