Jeg har fil fruit
med følgende indhold:
Apples, 12 Pears, 50 Cheries, 7 Strawberries, 36 Oranges, 2
Jeg vil gerne sortere de numeriske data for filen:
for(i=1;i<=NF;i++)j+=$i;printf "Fruit %d%s, %d\n",NR,OFS,$1,j | sort -k 2 > "numbers"; j=0"
For at køre awk-scriptet kører jeg kommandoen :
awk -f numbers fruit
Tallfilen har samme indhold som frugt, men dens første og andet felt kopieres til nummerfilen.
Kommentarer
Svar
GNU awk giver dig en pæn måde at kontrollere, hvordan du krydser en matrix: se Kontrol af Array Traversal og Styring af scanning
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
output
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
Svar
Du kan faktisk sende awk “s print
gennem "sort"
(bemærk citaterne):
$ 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
Så for at skrive til numbers
kan du gøre:
awk "{print "Fruit",NR, $0 | "sort -k 2 -t, -rn > numbers"}" fruit
Bemærk, at jeg forenklet din awk en smule. Det er ikke nødvendigt at bruge printf
her eller til eksplicit at udskrive OFS
da du ikke ændrer det nogen steder. Jeg al så se ikke hvad din for(i=1;i<=NF;i++)j+=$i
laver. Du har allerede nummeret med NR
, og din printf
brugte alligevel ikke j
.
Kommentarer
- I stedet for at kalde sort inde i awk er det ‘ enklere og mere effektivt at blot udskrive i awk og rør awk-output for at sortere:
awk '{print ...}' fruit | sort ...
. - @EdMorton åh, absolut! Jeg ville aldrig bruge denne tilgang selv, hvad ‘ er pointen? Men dette er hvad OPen bad om .
- Jeg finder ofte et krav om at sortere inden for gawk, når jeg ikke ‘ ikke vil sortere hele output. For eksempel indsamler og rapporterer statistik separat for hver inputfil. Jeg kan bruge en dekorere / sortere / klip metode til skræddersy enkle nøgler fra komplekse data (f.eks. rangere overbelastning af elektrisk udstyr ved hjælp af en sidematrix med maks. klassifikationer). Ekstern sortering bruger også diskarbejdsfiler og en split / fletningsstrategi. sortering kan bruge bedre metoder.
- @JoeSkora du behøver ikke ‘ behøver ikke at gyde en subshell fra awk og håber derefter at buffering fra alle berørte fører til output fra subshell kommer til stdout efter resten af output fra awk-kommandoen i stedet for før den eller, hvis relevant, i midten af den. Bare gør
awk '{print (NR>1), $0}' | sort -k1,1n -k2 | cut -d' ' -f2-
- @EdMorton Jeg kan godt lide at udskrive den betingede, gode idé. Den sidste del kan forenkles ved yderligere at forlade dette.
awk '{print (NR>1),$0}' | sort ... | cut -c3-
.
Svar
Jeg må have haft et seriøst problem med SunOS nawk i 2002. Jeg fandt mit testscript, der indeholdt tre awk-implementeringer, der kører inden for ikke-GNU awk:
(a) eSort: bruger en arbejdsfil og læser tilbage gennem en pipeløbende sorteringskommando. Ikke godt i mit tilfælde, fordi jeg lavede ting gennem ssh til agentløs overvågning, og eksterne arbejdsfiler var for invasive til vores live servere.
(b) qSort: en rekursiv partitionssort. Ydeevne er dårlig for store data og bryder stakken i mawk for> 2000 elementer. Sjovt at skrive dog.
(c) hSort: en sorterings-in-situ algoritme på 15 linjer. Denne bunke bruger en indekseringsalgoritme til at understøtte et binært træ (se Wikipedia).
Dette bash-script indeholder awk-funktioner hSort og hUp, der implementerer den aktuelle slags. Én handlingslinje placerer alle input i en matrix, og END-blokken kalder hSort og rapporterer resultaterne.
Inputdataene er indholdet af “man bash”, en gang som linjer og igen som ord. Vi bruger wc til at bevise, at intet gik tabt, og sorter -c for at bevise, at output er sorteret. Tidsindstillingerne inkluderer læse- og udskrivningsomkostningerne.
Dette er testbillede:
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
Dette er scriptet. Nyd!
#! /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
Svar
HeapSort kan skrives i standard awk på mindre mere end 20 linjer. Ikke blændende hurtigt, men det passer sproget rimeligt godt.
Kommentarer
- Åh, det gjorde jeg ikke ‘ t post det. Jeg hævdede dens eksistens og efterlod den som en øvelse for læseren.
- Sendte koden og testen den 9. januar 2020
asort
. Jeg kunne have svoret, at det ikke ‘ t, af en eller anden grund. Tak! Ikke helt sikker på, om det ville være det værd, da du ‘ skulle læse hele filen i en matrix og derefter sortere arrayet, så sortering af output ville sandsynligvis stadig være mere effektiv, men det ‘ er mere end nok til dette.asort()
det har også den langt mere nyttigesorted_in
, så du simpelthen kan definere en ordre forfor (i in array)
besøg matrixelementerne – se gnu.org/software/gawk/manual/gawk.html#Controlling-Scanning.I er enig i, at bare rørledning til UNIX-sortering ville være mere effektiv til dette problem.