Kuinka voin lajitella Linuxin awk-komentosarjassa?

Minulla on tiedosto fruit, jolla on seuraava sisältö:

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

Haluan lajitella tiedoston numeeriset tiedot:

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

awk-komentosarjan suorittamiseksi suoritan komennon :

awk -f numbers fruit 

Numerotiedostolla on sama sisältö kuin hedelmällä, mutta sen 1. ja 2. kenttä kopioidaan numerotiedostoon.

Kommentit

  • Miksi sinun on lajiteltava awk? Awkilla ’ ei ole natiivia lajitteluominaisuuksia, miksi

ei vain lajitella lähtöä sen sijaan? terdon GNU awkilla (joka on mielestäni Linuxin oletusarvoinen awk) on natiivilajitteluominaisuudet.

  • @EdMorton katso heidän viimeinen kysymyksensä jossain yhteydessä. Ja olet ’ oikeassa! GNU awk: lla on asort. Voisin jostain syystä vannoa, ettei se ollut ’ t. Kiitos! Ei ole varma, kannattaako se sen arvoa, koska ’ joudut lukemaan koko tiedoston matriisiksi ja sitten lajittelemaan taulukon, joten lähdön lajittelu olisi silti todennäköisesti tehokkaampaa, mutta se ’ on enemmän kuin tarpeeksi tähän.
  • @terdon Sillä ei ole ’ vain asort() siinä on myös paljon hyödyllisempi sorted_in, jotta voit määrittää yksinkertaisesti järjestyksen for (i in array) käy taulukkoelementeissä – katso gnu.org/software/gawk/manual/gawk.html#Controlling-Scanning.I olen samaa mieltä siitä, että vain putkisto UNIX-lajitteluun olisi tehokkaampi tätä ongelmaa varten.
  • @EdMorton GNU awk EI OLE oletusarvo debianissa ja vastaavissa. ” mawk ” on oletusarvo, jolla ’ ei ole ” asort ” sisäänrakennettu toiminto.
  • vastaus

    GNU awk antaa sinulle siistin tavan hallita taulukon läpi liikkumista: katso Taulukon liikkumisen hallinta ja Skannauksen hallinta

    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 

    tuotokset

    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 

    Vastaa

    Voit todella siirtää awk ”s print läpi "sort" (huomaa lainausmerkit):

    $ 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 

    Joten voit kirjoittaa osoitteeseen numbers, seuraavasti:

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

    Huomaa, että yksinkertaistin awk-tiedostoa hieman. Tällöin ei tarvitse käyttää printf -tulosta tai nimenomaisesti tulostaa OFS koska et muuta sitä missään. I al joten älä näe, mitä for(i=1;i<=NF;i++)j+=$i tekee. Sinulla on jo numero, jolla on NR, ja printf ei ollut missään tapauksessa käytössä j.

    Kommentit

    • Sen sijaan, että kutsutaan lajittelua awk: n sisällä, ’ on yksinkertaisempaa ja tehokkaampaa yksinkertaisesti tulostaa in awk ja putki awk-lähtö lajittelemaan: awk '{print ...}' fruit | sort ....
    • @EdMorton Voi, ehdottomasti! En koskaan käyttäisi tätä lähestymistapaa itse, mitä ’ s asia? Mutta tätä OP pyysi .
    • Löydän usein vaatimuksen lajittelusta gawk: n sisällä, kun en halua ’ halua lajitella koko tulosta. Esimerkiksi tilastojen kerääminen ja raportointi erikseen jokaiselle syötetiedostolle. Voin käyttää koristelu / lajittelu / leike -menetelmää räätälöi yksinkertaiset avaimet monimutkaisista tiedoista (esim. sijoita sähkölaitteiden ylikuormitukset käyttämällä enimmäisluokitusten sivuryhmää.) Ulkoinen lajittelu käyttää myös levytyötiedostoja ja split / merge -strategiaa. Lajittelu voi käyttää parempia menetelmiä.
    • @JoeSkora sinun ei ’ ei tarvitse kutea alahakua awk: stä ja toivoa sitten, että kaikkien osapuolten puskurointi johtaa tulokseen alikuoresta siirtymisestä stdoutiin awk-komennon lopputuloksen jälkeen ennen sitä tai tarvittaessa sen keskellä. Tee vain awk '{print (NR>1), $0}' | sort -k1,1n -k2 | cut -d' ' -f2-
    • @EdMorton Haluan tulostaa ehdollisen, loistavan idean. Viimeistä osaa voidaan yksinkertaistaa edelleen jättämällä tämä. awk '{print (NR>1),$0}' | sort ... | cut -c3-.

    vastaus

    Minulla on täytynyt olla vakava ongelma SunOS nawk -ohjelmassa vuonna 2002. Löysin testauskomentojeni, joka sisälsi kolme awk-toteutusta, jotka toimivat muualla kuin GNU-awk:

    (a) eSort: käyttää työtiedostoa ja lukee takaisin putkeajon lajittelukomennon kautta. Ei ole hyvä tapauksessani, koska tein juttuja ssh: n kautta agenttivapaata valvontaa varten, ja ulkoiset työtiedostot olivat liian invasiivisia live-palvelimillemme.

    (b) qSort: rekursiivinen osiolajittelu. Suorituskyky on huono suurille tiedoille ja rikkoo mawkin pinon> 2000 elementille. Hauska kirjoittaa.

    (c) hSort: lajittelu paikan päällä -algoritmi 15 rivillä. Tämä kasa käyttää indeksointialgoritmia tukemaan binääripuuta (katso Wikipedia).

    Tämä bash-komentosarja sisältää awk-funktiot hSort ja hUp, jotka toteuttavat varsinaisen lajittelun. Yksi toimintarivi sijoittaa kaiken syötteen matriisiin, ja END-esto kutsuu hSort-toiminnon ja raportoi tulokset.

    Syötetiedot ovat ”man bash” -sisältöä, kerran riveinä ja taas sanoina. Käytämme wc: tä osoittaaksemme, ettei mikään eksynyt, ja lajittelemalla -c todistamme, että lähtö on lajiteltu. Ajoitukset sisältävät luku- ja tulostuskulut.

    Tämä on testikuva:

    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 

    Tämä on komentosarja. Nauti!

    #! /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 

    Vastaa

    HeapSort voidaan kirjoittaa tavallisessa awk-muodossa vähemmän yli 20 riviä. Ei sokeasti nopeasti, mutta se sopii kieleen kohtuullisen hyvin.

    Kommentit

    • Voi, en ’ t lähetä se. Väitin sen olemassaolon ja jätin sen harjoitukseksi lukijalle.
    • Lähetetty koodi ja testi 9. tammikuuta 2020

    Vastaa

    Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *