Shellové skriptovanie: najdlhší riadok v súbore

Boli časy, boli, ale sa minuli, keď bolo treba nájsť najdlhší riadok v súbore (aby sa v C mohol alokovať dostatočne dlhý riadok pre fgets()).

Pome! [Na GNU systémoch]

Ak máme GNU systém (teda bežný Linux), je to jednoduché:

wc -L /etc/passwd

Ale na BSD variantoch, medzi ktoré patrí MacOS, či na starých UNIXoidoch (AIX) to nestačí.

Vďaka Mariánovi Novákovi za prst do manuálu k tomuto parametru.

Pome! [Na MacOSoch]

Jedna zo zoznamovitých úvah ide takto: pre každý riadok spočítame jeho dĺžku, riadky zotriedime podľa dĺžky a vezmeme z výsledku poslednú (najväčšiu) hodnotu.

Inak povedané, zoznam riadkov namapujeme na zoznam dĺžok, ten potriedime a vytiahneme z neho posledný prvok.

Ak máme awk, je to radosť: ten vie pracovať s riadkami jedna radosť. Stačí urobiť pre každý riadok akciu “vytlač dĺžku riadka”, a tú zistíme z internej funkcie length.

Výsledok prerúrujeme do sortu, ktorý to potriedi a posledný prvok vytiahneme tailom:

awk '{print length}' /etc/passwd | sort | tail -n1

Pome! Aj s konkrétnym riadkom

Toto samozrejme vypíše len jedno číslo. Ale ja chcem vidieť aj oný riadok!

Tu už musíme viac awkovať: použime klasickú programátorskú fintu s hľadaním maxima.

Pre každý riadok zistíme, či jeho dĺžka je väčšia než doposiaľ dosiahnuté maximum a ak áno, aktualizujeme nové maximum a poznačíme si celý riadok. Na konci súboru všetko vypíšeme a máme to.

Skript maxdlzka.awk by vyzeral:

{ 
    if( length > max )
    { 
        max = length 
        riadok = $0 
    } 
} 

END { 
    print max "|" riadok
}

V tomto skripte máme dve pravidlá: jedno pre každý riadok a jedno END po konci súboru.

Premenná $0 obsahuje celý aktuálne spracovávaný riadok, a ostatné premenné netreba nijak deklarovať, ani inicializovať.

Posledná podivná vec je tlač: print má viacero parametrov oddelených medzerami: čiže vytlačí obsah premennej max, za ňu dolepí pajpu | a za ňu premennú riadok.

A potom:

awk -f maxdlzka.awk /etc/passwd

Ako správni hardcoráci to môžeme napísať aj na jeden riadok:

awk '{ if( length > m ) { m = length; l = $0 } } END { print m "|" l }' /etc/passwd

Pridaj komentár

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *