nav_dugme codeBlog codeBlog
  • početna Početna stranica
  • Sačuvani članci Sačuvani članci
  • Članci
     (spisak)
  • Kontakt
Povratak na vrh stranice

Info & povezani članci Info o članku - dugme

Info

trejler_sat Datum objave: 19.09.2022.

trejler_dokument Jezici: Shell

trejler_teg_narandzasti Težina: 7/10

linux
gnu/linux
unix
open source
slobodni softver
Shell
regularni izrazi
regex
komandna linija
datoteke
obrada teksta
teorija
saveti
zanimljivosti

Tema: GNU/Linux

1. deo - Uvod2. deo - Osnovne komande4. deo – Shell skripte i automatizacija procesa

Povezani članci

ASCII, UNICODE i UTF - Predstavljanje znakova na računarimaUNIX Time - Predstavljanje datuma i vremena na računarimaIzbor prvog programskog jezikaRegularni izrazi - napredna pretraga tekstaPokretanje lokalnog web serveraUvod u PythonPostfiksna notacija - kako računari računaju?Operacije sa tekstualnim datotekama u programskim jezicima C i PythonŠablonske niske u programskim jezicimaCallback funkcije i lambda izraziOperacije sa bitovima u programskom jeziku CKako napraviti syntax highlighter
Svi članci
Controlling complexity is the essence of computer programming.
Brian Kernighan

GNU/Linux - 3. deo – Napredne komande

Facebook LinkedIn Twitter Viber WhatsApp E-mail
zoom_plus zoom_minus bookmark
početna > Članci > Teorija

Uvod

Temeljno poznavanje osnovnih komandi, važan je preduslov za efikasno obavljanje poslova koji su vezani za razvoj softvera ili projektovanje web sajtova u nekom od UNIX-olikih okruženja, međutim, u praksi je više nego preporučljivo biti upoznat i sa izvesnim brojem naprednijih programa za obradu teksta u konzoli (bar nekoliko), * preko kojih se rezultat izvršavanja osnovnih komandi može izmeniti, filtrirati ili formatirati na prikladniji način.

Pored napredni(ji)h komandi za obradu teksta, administracija sistema takođe obuhvata (bar povremeno) korišćenje shell skripti. **

Pod naprednom obradom teksta (da pojasnimo), ovoga puta ne podrazumevamo upotrebu konzolnih editora kao što su Vim ili Emacs, već mislimo na rad sa tekstom u okviru komandne linije, to jest, na upotrebu programa kao što su grep, sed i awk, koji po potrebi primaju tekst sa standardnog ulaza, obavljaju obradu i šalju tekst na standardni izlaz.

* Kao i obično, preporučujemo da se ne upuštate u savladavanje novih veština ukoliko veštine sa prethodnog nivoa niste savladali na odgovarajući način.

** Alatima za naprednu obradu teksta u konzoli bavićemo se u ovom članku, a shell skripte (i još nekolicina drugih mehanizama za automatizaciju), biće tema sledećeg članka.

Još nekoliko uvodnih napomena ....

Pošto polako zalazimo u oblast naprednijih UNIX komandi, želimo da što pravilnije "naštimamo" očekivanja čitalaca, i stoga ćemo se ukratko osvrnuti na određene pojave ....

Može se reći da oblast UNIX/Linux komandi predstavlja svojevrstan "okean" (pojavu koju odlikuje: i velika širina, i velika dubina), i stoga, sam termin "napredne komande" koji smo izabrali za naslov članka (odnosno, preciznije - "iskazani nivo naprednosti"), može biti protumačen na više načina.

Sa jedne strane, u odnosu na određene komande, tj. programe (koje nismo pominjali do sada, a "kakvih inače ima na Linux-u"), komande koje ćemo prikazati u ovom članku ne deluju 'posebno napredno'.

Sa druge strane - same po sebi - prilično su napredne!

U članku neće biti prikazane sve opcije svih programa (ni iz daleka, pogotovo kada je u pitanju program awk), ali, bez obzira na navedeno, opcije koje ćemo prikazati, same po sebi omogućavaju prilično napredne vidove obrade teksta (uz mnoštvo zanimljivih kombinacija).

Najprostije bismo mogli reći da će u članku biti prikazan "osnovni nivo naprednijih komandi" (pri čemu je akcenat na prikazivanju ideja koje stoje iza samih alata i praktičnim primerima, a ne "na nabrajanju opcija").

Tehnike koje ćemo prikazati u nastavku, u praksi su sasvim dovoljne (uz bar ponešto samostalnog istraživanja i 'nadogradnje'), za korisnike koji ne žele previše da se udubljuju u tematiku konzolnih komandi pod Linux-om, već samo žele što bolju osnovu za korišćenje drugih programa (recimo da se navedeno odnosi na dobar deo programera), ali - takođe se može reći i da je gradivo iz članka sasvim dobra osnova za čitaoce koji žele da istražuju nadalje i što više se udube u tematiku.

Doduše, kad je u pitanju takvo udubljivanje .... "budite upozoreni" 🙂 ....

Komande u terminalu (kao što smo naveli još u uvodnom članku), na početku pomalo "žuljaju" većinu korisnika koji su navikli na GUI interfejs, ali, uz iole ozbiljniju količinu uloženog truda, nije teško navići se (odnosno, nije teško prevazići 'početne neudobnosti').

Međutim (na ovom mestu dolazimo do prave poente): ukoliko neko istraje i ne izgubi interesovanje, lako i neosetno vremenom dolazi u situaciju u kojoj, ne samo da Linux komande "ne žuljaju", već, naprotiv - pobuđuju interesovanje na dubokom ličnom nivou (i stoga trošenje više sati na proučavanje sitnih detalja, nije više "kuluk", već počne da deluje kao zabava).

Srećom, navedene 'zanimacije' su sasvim u skladu sa akademskim obrazovanjem i profesionalnim usavršavanjem mlađih programera, i sve naučeno, najčešće veoma dobro dođe u praksi.

U budućnosti, sasvim lako nam može pasti na pamet da napišemo i članak koji obuhvata mnogo više opcija i primera koji su vezani za programe grep, sed i awk - a sada je vreme da se vratimo na posao ....

Grep - pretraga teksta preko regularnih izraza

Program grep (skraćenica za "globally search for a regular expression and print matching lines"), pronalazi linije teksta koje se poklapaju sa određenim obrascem.

Tekst koji se pretražuje može biti izlaz prethodne komande (koji se "pajpuje" u grep), a mogu se takođe direktno pretraživati i tekstualne datoteke (u tom slučaju, naziv datoteke je jedan od argumenata).

Komanda grep poziva se po sledećoj šemi:

		
$ grep [opcije] obrazac [datoteka]
		
	
Slika 1. - Opšta šema izvršavanja programa grep.

Sa prosleđivanjem (tj. "pajpovanjem") izlaza određene komande u program grep, već smo se upoznali u uvodnom članku ....

		
$ ls -la | grep 'Sep 26'

2.4K  Nov 26  00:44
50K   Nov 26  08:33
143   Nov 26  11:54
		
	
Slika 2. - Primer pajpovanja izlaza komande ls u program grep.

.... a ovoga puta više pažnje ćemo obratiti na primere pretrage teksta koji se učitava direktno iz datoteka.

.... naravno, uz napomenu da svi vidovi pretrage sa kojima ćemo se u nastavku upoznati, važe i onda kada se tekstualni izlaz prethodno izvršenog programa pajpuje u grep zarad dalje obrade.

Pretraga teksta iz datoteka

Datoteka koju ćemo koristiti za primere u članku, sadrži (fiktivne) podatke o osobama koje učestvuju u održavanju velike društvene mreže. Po id-ovima se da naslutiti da mreža ima više stotina hiljada korisnika, ali, koristimo sažetu listu koja je dobijena filtracijom veće tabele (u kojoj su zapisani svi korisnici, uključujući i osoblje sajta).

		
# Ime    Prezime    priv  funkcija  datum_rođenja  id 
---------------------------------------------------------
1 Milan  Jovanović  30    admin     1984-10-15     162
2 Dejan  Kovačević  30    admin     1981-03-21     1770
3 Ivana  Marković   20    moderator 1986-11-01     18324
4 Petar  Komnenović 10    saradnik  1992-08-08     19427
5 Jelena Spasić     10    saradnik  1985-01-12     191981
6 Nevena Katić      10    saradnik  2000-04-05     204628
7 Oliver Petrović   10    saradnik  1993-09-04     215283
8 Stojan Milić      10    saradnik  1995-03-05     294648
		
	
Slika 3. - Sadržaj datoteke saradnici.txt, koju ćemo koristiti u primerima.

Datoteku možete preuzeti preko sledećeg linka: saradnici.txt (uz napomenu da datoteka sadrži i kolonu sa email adresama, koju smo u prikazu u članku izostavili zarad preglednosti).

Za početak, pozabavićemo se jednostavnom pretragom, bez regularnih izraza.

Ukoliko upotrebimo sledeći jednostavan obrazac ....

		
$ grep 'admin' saradnici.txt 
		
	
Slika 4. - Pretraga niske "admin" u datoteci saradnici.txt.

.... pretraga daje rezultat koji je korektan (i očekivan):

		
1 Milan  Jovanović  30    admin     1984-10-15     162
2 Dejan  Kovačević  30    admin     1981-03-21     1770
		
	
Slika 5. - Rezultat izvršavanja prethodne komande.

Međutim, ako pokušamo - po istom principu - da pronađemo osobu (ili osobe), pri čemu se kao kriterijum koristi 'godina rođenja':

		
$ grep '1981' saradnici.txt 
		
	
Slika 6. - Primer pretrage koja neće vratiti očekivani rezultat.

.... rezultat neće biti u skladu sa očekivanjima (jer, "moglo bi se reći" - da samo tražimo običnu nisku koja se može protumačiti na više načina):

		
2 Dejan  Kovačević  30    admin     1981-03-21     1770
5 Jelena Spasić     10    saradnik  1985-01-12     191981
		
	
Slika 7. - Rezultat izvršavanja prethodne komande.

U jednom redu, uneta niska (zaista) predstavlja godinu rođenja, dok u drugom redu niska predstavlja (samo) deo id-a saradnika.

Bez odgovarajućih mehanizama za prepoznavanje obrazaca, jasno je da rezultati obične pretrage mogu biti diskutabilni i inače (pogotovo u većim kolekcijama tekstualnih podataka), i upravo to smo hteli da potcrtamo preko jednostavnog primera.

U konkretnom primeru, problem se može rešiti na trivijalan način, budući da su podaci u datumima rođenja saradnika razdvojeni crticama (i stoga bi pretraga niske "1981-" sasvim urodila plodom),

Međutim, zarad opšteg obrazovanja (to jest, zbog toga što u mnogim drugim situacijama nije toliko jednostavno pronaći "priručno rešenje"), "pravićemo se" da ne vidimo jednostavni obrazac i sprovešćemo pretragu preko regularnog izraza.

U slučaju da se u drugim kolonama ne pojavljuju datumi (niti drugi podaci koji po svom formatu 'liče' na datume), regularni izraz, odnosno, cela komanda pretrage - koja prepoznaje datume koji pripadaju ranije navedenoj godini - može se definisati na sledeći način:

		
grep -E '\b1981-[[:digit:]]{2}-[[:digit:]]{2}\b' saradnici.txt
		
	
Slika 8. - Komanda koja pretražuje saradnike po godini rođenja, preko regularnih izraza.

Zapažamo argument -E (--extended-regexp) - preko koga se uključuje upotreba regularnih izraza, a zapažamo i 'dvostruku' pojavu argumenta \b (boundary) - preko koga se u regularnim izrazima prepoznaju granice reči (tj. znakovi kao što su razmaci, tabovi, crte i drugi specijalni znaci koji ograničavaju pojedinačne reči).

Pored navedenog, vidimo i to da se određene klase znakova (u programu grep), označavaju drugačije u odnosu na sintaksu koju smo prikazali u uvodnom članku o regularnim izrazima.

U većini drugih regex implementacija, klasa znakova preko koje se prepoznaju cifre, tipično se označava kao: \d, što znači da bi regularni izraz bio zapisan drugačije: 1981-\d{2}-\d{2}).

U svakom slučaju (u najopštijem smislu): potrebno je naći nisku koja počinje sa "1981", posle čega sledi crtica, zatim, dve cifre (koje praktično predstavljaju mesec), zatim, ponovo crtica i - na kraju - ponovo dve cifre (koje predstavljaju dan).

Prethodno definisana pretraga sada vraća jedinog kandidata koji je (zapravo) rođen navedene godine.

		
2 Dejan  Kovačević  30    admin     1981-03-21     1770
		
	
Slika 9. - Rezultat izvršavanja prethodne komande.

Ako se datumi pojavljuju u više kolona, situacija više nije jednostavna i potrebno je koristiti program koji je u stanju da pristupa pojedinačnim poljima u okviru reda, tako da budemo sigurni da se pretražuju podaci iz (npr) četvrte kolone, a ne podaci iz sedme kolone i sl (isto važi i za pretragu drugih formata koji se pojavljuju u više kolona).

Za zadatke kakve smo naveli (i druge komplikovanije zadatke), tipično se koristi program awk (videćemo u nastavku više praktičnih primera).

Takođe, zadržaćemo se na jednostavnijim regex obrascima (i za grep, i za druge programe), da ne bismo skretali pažnju čitalaca sa principa funkcionisanja programa koje prikazujemo.

Dakle, ozbiljniji zahvati praktično zahtevaju upotrebu kompleksnijih programa (u članku ćemo koristiti program awk kome ćemo uskoro posvetiti više pažnje), međutim - kako to obično biva - upotreba moćnijih programa podrazumeva i upotrebu kompleksnije sintakse, i stoga se vredi zadržati na upotrebi programa grep za zadatke "manje i srednje težine".

Da pojasnimo preko dodatnog primera ....

U prvom primeru, tražili smo redove sa podacima o administratorima sajta, a ako bi bilo potrebno pronaći: administratore (nivo privilegija 30) i moderatore (nivo privilegija 20), i takav zadatak bi se mogao obaviti korišćenjem programa grep - pod uslovom da pažljivo postupimo po pitanju toga koji podatak ćemo koristiti kao kriterijum za pretragu.

Sledeća pretraga:

		
$ grep -E 'admin|moderator' saradnici.txt 
		
	
Slika 10. - Pravilan način pronalaženja saradnika sa funkcijom admin, preko regularnih izraza.

.... vraća željeni rezultat, ali zato "idejno slična" pretraga, nalik na sledeću pretragu:

		
$ grep -E '20|30' saradnici.txt
		
	
Slika 11. - Nepravilan način pronalaženja saradnika sa funkcijom admin, preko regularnih izraza..

.... vraća vrlo diskutabilne rezultate, jer nimalo (!) nije teško zamisliti da niska "20" ili "30" može biti dan rođenja, deo niske id, ili deo nekog drugog podatka.

Međutim, postoje i drugi detalji o kojima se mora voditi računa.

Recimo, ako postoji šansa da se među email adresama pronađu podniske "admin" i "moderator" (npr. ukoliko postoje korisnici sa email adresama: superadmin2000@gmail.com i veselimoderator@gmail.com i sl) - stvari se komplikuju.

U konkretnom primeru, gotovo je sigurno da se problem može rešiti uz upotrebu argumenta \b, ali, kao što smo već nagovestili, u (drugim) kritičnim situacijama, prepoznavanje sadržaja pojedinačnih polja (tj. kolona), u redovima, najsigurnije je obaviti preko programa awk.

Videćemo kasnije kako preko programa awk možemo rešiti zadatak pronalaženja korisnika čiji je nivo privilegija veći ili jednak 20, ali, pre nego što dođemo do toga, razmotrićemo i nekoliko dodatnih opcija vezanih za program grep.

Numeracija redova

Uz argument -n (--line-number), komanda grep prikazuje i redne brojeve linija iz datoteke (na kojima dolazi do poklapanja):

		
$ grep -n 'admin' saradnici.txt

3:1 Milan  Jovanović  30    admin     1984-10-15     162
4:2 Dejan  Kovačević  30    admin     1981-03-21     1770
		
	
Slika 12. - Numeracija redova u programu grep.

Inverzija pretrage

Uz argument -v (--invert-match), pretraga vraća sve redove koji ne sadrže (pod)niske koje odgovaraju navedenom obrascu pretrage:

		
$ grep -E -v '\b19[[:digit:]]{2}\b' saradnici.txt

6 Nevena Katić      10    saradnik  2000-04-05     204628
		
	
Slika 13. - Inverzija pretrage u programu grep.

U gornjem primeru, videli smo pretragu koja vraća sve saradnike čije godište ne počinje sa "19" (u datoteci "saradnici.txt", pojavljuje se samo jedan takav saradnik).

Prikaz prethodnih redova

Uz argument -B (--before-context), posle čega sledi brojčana vrednost (na primer 2), rezultat sadrži - pored pronađenih redova - takođe i navedeni broj redova koji prethode pronađenim redovima.

		
$ grep -B2 '\b1985\b' saradnici.txt

3 Ivana  Marković   20    moderator 1986-11-01     18324
4 Petar  Komnenović 10    saradnik  1992-08-08     19427
5 Jelena Spasić     10    saradnik  1985-01-12     191981
		
	
Slika 14. - Prikaz redova koji prethode pronađenim redovima, preko argumenta "-B" (before).

Prikaz sledećih redova

Uz argument -A (--after-context), posle čega sledi brojčana vrednost (na primer 2), rezultat sadrži - pored pronađenih redova - takođe i navedeni broj redova koji slede posle pronađenih redova.

		
$ grep -A2 '\b1985\b' saradnici.txt

5 Jelena Spasić     10    saradnik  1985-01-12     191981
6 Nevena Katić      10    saradnik  2000-04-05     204628
7 Oliver Petrović   10    saradnik  1993-09-04     215283
		
	
Slika 15. - Prikaz redova koji slede posle pronađenih redova, preko argumenta "-A" (after)..

Naravno, prethodne dve opcije moguće je i kombinovati:

		
$ grep -B2 -A2 '\b1985\b' saradnici.txt

3 Ivana  Marković   20    moderator 1986-11-01     18324
4 Petar  Komnenović 10    saradnik  1992-08-08     19427
5 Jelena Spasić     10    saradnik  1985-01-12     191981
6 Nevena Katić      10    saradnik  2000-04-05     204628
7 Oliver Petrović   10    saradnik  1993-09-04     215283
		
	
Slika 16. - Kombinovanje opcija "-B" i "-A".

Pretraga teksta se tipično obavlja preko programa grep, ali, zamena teksta se tipično obavlja preko programa sed (ili awk, ukoliko postoji potreba za dodatnim vidovima obrade).

Sed - zamena teksta

Program sed (Stream Editor), omogućava obavljanje raznovrsnih operacija nad ulaznim niskama, ali, u praksi se tipično koristi za izmenu delova ulaznog teksta.

Sam po sebi, sed je krajnje zanimljiv i prilično moćan program za obradu teksta, ali, za komplikovanije zahvate, u praksi se najčešće (ipak) koristi program awk (tema sledećeg odeljka, i objektivno još moćniji program).

Kao što smo prethodno nagovestili: u Linux terminalu (u uobičajenim situacijama), komanda grep praktično predstavlja ekvivalent opcije "search" (sa kakvom se inače srećemo u editorima teksta), dok je komanda sed praktično ekvivalent opcije "replace".

Zamena teksta preko programa sed izvršava se po sledećoj šemi:

		
$sed 'operacija/postojeći_obrazac/novi_tekst/' ulazna_datoteka
		
	
Slika 17. - Opšta šema izvršavanja programa sed.

Komande se zadaju unutar niske, a argument "operacija" označava jednu od mogućih internih komandi za obradu teksta.

U praksi, ako se komanda pozove na sledeći način (pri čemu je interna komanda zadata preko argumenta s koji označava zamenu ("s" - skraćeno od "substitute")) ....

		
$ sed 's/saradnik/operator/' saradnici.txt
		
	
Slika 18. - Primer zamene podniski preko programa sed.

.... svaka pojava niske "saradnik" biće zamenjena niskom "operator", pri čemu će rezultat biti prikazan u terminalu.

Kada kažemo "u terminalu", na posredan način smo nagovestili da pozivi komandi grep i sed ne podrazumevaju trajnu izmenu sadržaja (ulazne) datoteke!

Za trajno čuvanje - iako same komande nude mogućnost operisanja direktno nad sadržajem datoteka (preko dodatnih opcija) - najpraktičnije je koristiti redirekciju:

		
$sed 's/postojeci_obrazac/novi_tekst/' ulazna_datoteka > nova_datoteka
		
	
Slika 19. - Primer redirekcije rezultata izvršavanja programa sed (to jest, praktično: upis podataka u datoteku).

Kad smo već kod praktičnosti, naveli smo da se za komplikovanije primere obrade najčešće koristi program awk, ali, svakako želimo da zainteresujemo čitaoce da dodatno istražuju i program sed, i stoga ćemo prikazati još koji primer.

Recimo, ukoliko je potrebno ograničiti dejstvo komande sed na određeni raspon redova, može se koristiti opcija -n:

		
sed -n '3,10p;s/saradnik/operator/g' saradnici.txt
		
	
Slika 20. - Primer ograničavanja dejstva programa sed na raspon redova (između trećeg i desetog), preko argumenta "-n".

Ako pokrenemo poslednju komandu, zaglavlje se (praktično) preskače, što znači da će pretraga i zamena početi od 3. reda (odnosno: u obzir će biti uzeti samo redovi koji sadrže slogove sa podacima).

U prethodnom primeru, znali smo da datoteka sadrži 10 redova, međutim, ponekad nećemo 'znati unapred' i, u takvim situacijama, komanda se može dodatno uopštiti uz navođenje znaka $, koji predstavlja oznaku za poslednji red:

		
sed -n '3,$;s/saradnik/operator/g' saradnici.txt
		
	
Slika 21. - Primer ograničavanja dejstva programa sed na raspon redova, od trećeg reda nadalje, preko argumenta "-n".

Zamena pronađenih obrazaca drugim niskama, jeste tipična namena programa sed, međutim, program se takođe može koristiti i za uklanjanje redova koji odgovaraju pronađenom obrascu (što se postiže preko interne komande d ('delete')),:

		
sed '/^[[:space:]]*$/ d' saradnici.txt
		
	
Slika 22. - Primer uklanjanja praznih redova preko programa sed.

Prethodno navedena komanda pronalazi - i uklanja - sve redove koji su prazni ili sadrže samo whitespace znakove.

Dva prethodno navedena programa (uz korišćenje tehnika pajpovanja i redirekcije), znatno proširuju osnovne mogućnosti programa sa kojima smo se upoznali u prethodnim člancima i veoma dobro dođu u velikom broju situacija, ali, rekli bismo da je "zvezda večeri" kada je u pitanju precizna i sveobuhvatna obrada teksta u Linux terminalu - program AWK.

AWK - napredna manipulacija tekstom

U najpraktičnijem smislu, program awk je zapravo svojevrstan interpretator za specijalizovani programski jezik (sa C-olikom sintaksom, posebnim promenljivama, kontrolnim strukturama i ugrađenim funkcijama), i u pitanju je programski jezik koji je specifično namenjen (naprednoj) obradi teksta.

"AWK" je akronim sačinjen od početnih slova prezimena koautora programa: Alfred Aho, Peter J. Weinberger i Brian Kernighan.

Za početak, može se reći da izvršavanje programa awk funkcioniše po sledećem obrascu:

		
$ awk obrazac { izvršne_komande } ulazna_datoteka
		
	
Slika 23. - Opšta šema izvršavanja programa awk.

.... ali, princip funkcionisanja lakše je razumeti uz primere (a opšta šema koju smo prethodno prikazali, uvek može biti nešto na šta ćete se vraćati povremeno, zarad boljeg razumevanja različitih konkretnih primera).

U prvom primeru, razmotrićemo situaciju u kojoj je potrebno izdvojiti samo one redove koji sadrže slogove sa saradnicima (i dalje se služimo podacima iz datoteke saradnici.txt), a prvo što nam može pasti na pamet, jeste to da se problem može rešiti upotrebom regularnih izraza.

Mi se "pravimo da ne znamo" da postoji elegantniji način; čitaoci se takođe prave da ne naslućuju da je tako (a zapravo samo želimo da se nadovežemo na ideje koje smo već koristili, i da pokažemo da se regularni izrazi mogu koristiti i u programu awk).

Ako se filtracija redova obavlja preko regularnih izraza (u primeru koji razmatramo), biće pretraživani redovi koji počinju cifrom:

		
awk '/^[0-9]/ { printf("%s %s %s\n", $2, $3, $5) }' saradnici.txt
		
	
Slika 24. - Primer izdvajanja kolona (uz korišćenje regularnih izraza), iz redova koji počinju cifrom.

.... a blok sa izvršnim komandama, podrazumeva ispis tri specifične kolone.

Komanda koju smo videli, pruža priliku da se detaljnije pozabavimo strukturom instrukcija koje su argumenti programa awk: *

  • u prvom delu naredbe ("obrazac"), pojavljuje se regularni izraz ^[0-9], preko koga se prepoznaju linije koje počinju cifrom - i to su linije koje će program obrađivati (drugim rečima - linije koje ne odgovaraju obrascu - biće zanemarene)
  • izvršne komande, oivičene vitičastim zagradama { .... }, obuhvataju (u primeru koji razmatramo), formatirani ispis nekoliko proizvoljno izabranih kolona preko komande printf (u pitanju je C-olika sintaksa, što naravno ne čudi, budući da je program awk razvijen u istoj "softverskoj kuhinji" kao i programski jezik C)
  • u (internoj) komandi printf, kao argumenti se koriste specijalne promenljive: $2, $3 i $5, koje odgovaraju poljima (tj. "kolonama") u redu koji se trenutno obrađuje, i praktično su u pitanju: ime ($2) i prezime saradnika ($3), kao i funkcija koju saradnik obavlja ($5)
  • kao ulaz, koristi se ista datoteka koju smo i do sada koristili u primerima

* Praktično je u pitanju mini-skripta za obradu teksta (a možemo primetiti da je program awk inače u stanju da pokreće i znatno veće "skripte" za obradu teksta, koje često nalikuju pravim programima).

Program uzima u obzir jednu po jednu liniju i, ukoliko nije naveden uslov (tj. "obrazac"), u obradi će biti korišćeni svi redovi.

U gornjem primeru, kao što smo već naveli - postoji uslov (obrazac pretrage koji određuje da se na izlaz šalju (samo) redovi koji počinju cifrom, što u praktičnom smislu znači: redovi sa podacima o saradnicima).

Postoji način (kao što ćemo videti u nastavku), da se kao kriterijum za izdvajanje koristi i broj polja u datom redu, kao i redni broj samog reda.

U svakom slučaju, kada linija dospe na obradu, ceo slog (tj. pojedinačni red ulaznog teksta), deli se preko niske koja je definisana kao separator (podrazumevani separatori su razmaci i tabovi, ali, mogu se definisati i proizvoljne niske), a u daljoj obradi može se pristupati:

  • celom redu, preko promenljive $0
  • pojedinačnim poljima (tj. 'kolonama'), preko promenljivih $1, $2, $3 .... $n (gde n predstavlja indeks poslednje kolone)

.... pri čemu su definisane još dve korisne promenljive:

  • NF (Number of Fields) - ukupan broj polja (tj. kolona) u trenutnom redu
  • NR (Number of Records) - ukupan broj redova

Promenljive NR i NF mogu se koristiti i kao deo obrasca za proveru, koji prethodi izvršnim komandama za formatiranje (slede primeri) ....

Pošto smo sagledali dodatne opcije, jasno je da se slogovi sa podacima saradnika mogu izdvojiti mnogo lakše preko jednostavnog uslova NR>2 ("redni broj sloga veći od 2" (prva dva reda u tabeli predstavljaju formatirano zaglavlje)):

		
awk 'NR>2 { printf("%s %s %s\n", $2, $3, $5) }' saradnici.txt
		
	
Slika 25. - Primer izdvajanja kolona, iz redova sa rednim brojem koji je veći od 2 (ovoga puta, umesto regularnog izraza, koristi se uslov).

.... i rezultat je skoro isti kao u prvom pozivu.

Kažemo "skoro", jer biće ispisan i poslednji red koji je prazan, što, u praksi, verovatno (?!) ne predstavlja problem.

Program awk ne biva zakočen time što se pozivaju argumenti kao što su (na primer) $1, $4, ili $17 koji ne postoje u praznom redu, ali, ukoliko se izlaz šalje u drugi program - u kome bi pojava nepravilno formatiranog ulaza mogla dovesti do zastoja - potrebno je da budemo sasvim precizni.

U smislu 'povećanja preciznosti', lako se može urediti da se u rezultatu pojave samo redovi koji sadrže tekst (na primer, preko uslova koji proverava da li je ukupan broj polja u trenutnom redu (promenljiva NF), veći od 0): *

		
awk 'NR>2 && NF>0 { printf("%s %s %s\n", $2, $3, $5) }' saradnici.txt
		
	
Slika 26. - Primer izdvajanja kolona, iz redova sa rednim brojem koji je veći od 2 (pri čemu je broj polja u redu veći od 0).

* Promenljiva NF ima vrednost 0 u slučaju da je red prazan, a pitate se verovatno i zašto smo (o)stavili uslov NR>2?

U opštem smislu, može se reći da je krajnje uputno da se naredba napiše tako da program awk ne pretražuje redove za koje je unapred poznato da ne mogu sadržati bitne podatke (što se posebno odnosi na primere koji su (primetno) obimniji od primera koji smo prikazali).

Još je bolje ako se napiše uslov koji doslovno proverava da li red sadrži tačno onoliko kolona koliko je predviđeno (u našem slučaju 7):

		
awk 'NR>2 && NF==7 { printf("%s %s %s\n", $2, $3, $5) }' saradnici.txt
		
	
Slika 27. - Primer izdvajanja kolona, iz redova sa rednim brojem koji je veći od 2 (pri čemu se izdvajaju redovi koji imaju tačno 7 polja tj. kolona).

U daljoj obradi, preko prethodno izdvojenih podataka, lako se može uobličiti (na primer), SQL upit za unos sloga u bazu podataka:

		
printf("INSERT INTO saradnici (ime, prezime, funkcija) VALUES('%s', '%s', '%s');\n", $2, $3, $5)
		
	
Slika 28. - Primer korišćenja komande awk za formatiranje SQL upita.

Zarad preglednosti prikazali smo samo deo sa komandom printf (ostatak je isti kao na prethodnoj slici).

"Da sve bude još bolje", izlaz se lako može pajpovati u program preko koga se standardni ulaz prosleđuje u tekstualni clipboard operativnog sistema:

		
awk 'prethodni uslovi i printf' datoteka | xclip -selection clipboard
		
	
Slika 29. - Primer usmeravanja rezultata obrade prethodne komande u tekstualni clipboard operativnog sistema.

U većini situacija, programi koje smo do sada naveli: ls, cp, mv .... grep, sed i awk, tipično predstavljaju deo osnovnog paketa instaliranih programa na većini GNU/Linux distribucija, dok sa programom xclip to tipično nije slučaj, što znači da se program xclip (kao i mnogi drugi programi), mora instalirati zasebno.

Prikazaćemo prethodnu komandu i u celosti (iako je ponešto "glomazna"):

		
awk 'NR>2 && NF==7 { printf("INSERT INTO saradnici (ime, prezime, funkcija) VALUES (\"%s\", \"%s\", \"%s\");\n", $2, $3, $5) }' saradnici.txt | xclip -selection clipboard
		
	
Slika 30. - Prikaz komande za formatiranje SQL upita i slanje rezultata u clipboard (ovoga puta, komanda je prikazana u celosti).

Za kraj početnog upoznavanja sa komandom awk, * vratićemo se na primer pronalaženja korisnika iz tabele, čiji je nivo privilegija veći ili jednak 20 ....

Budući da program awk omogućava precizan pristup poljima u okviru reda (a pri tom raspolaže i strukturama za kontrolu toka programa), lako se može proveriti da li podatak u 4. koloni zadovoljava uslov koji je naveden u prethodnom pasusu:

		
awk 'NR>2 && NF==7 && $4>=20 { printf("%s %s %s\n", $2, $3, $5) }' saradnici.txt
		
	
Slika 31. - Primer pronalaženja saradnika preko nivoa privilegija (administratori i moderatori).

.... pri čemu se (očekivano) dobija sledeći rezultat:

		
Milan Jovanović admin
Dejan Kovačević admin
Ivana Marković moderator
		
	
Slika 32. - Rezultat izvršavanja prethodne komande.

Razmotrićemo još i dve jednostavne komande za formatiranje izlaza.

* Iskoristićemo komandu awk nadalje u ovom članku za nekoliko jednostavnih primera, a svakako ćemo se u narednim člancima upoznati i sa drugim opcijama komande awk.

Sort - uređivanje redova

Program sort uređuje redove ulaznog teksta shodno zadatom kriterijumu (uređivanje podrazumeva premeštanje redova jednih ispod drugih, a kriterijum je sadržaj nekog od polja).

Ako komanda awk ....

		
awk 'NR>2 && NF==7 { printf("%s %s %s\n", $2, $3, $6) }' saradnici.txt
		
	
Slika 33. - Primer korišćenja komande awk za ispis podataka o saradnicima (pri čemu će rezultat nadalje biti sortiran preko komande sort).

.... vrati sledeći izlaz:

		
Milan Jovanović 1984-10-15
Dejan Kovačević 1981-03-21
Ivana Marković 1986-11-01
Petar Komnenović 1992-08-08
Jelena Spasić 1985-01-12
Nevena Katić 2000-04-05
Oliver Petrović 1993-09-04
Stojan Milić 1995-03-05
		
	
Slika 34. - Rezultat izvršavanja prethodne komande.

.... rezultat se može dodatno sortirati preko komande sort:

		
awk_prethodni | sort -k 3
		
	
Slika 35. - Primer sortiranja rezultata preko komande sort.

Argument -k 3 označava da se kao kriterijum za sortiranje koristi treća kolona (praktično, datum rođenja).

Tabela sada ima sledeći oblik:

		
Dejan Kovačević 1981-03-21
Milan Jovanović 1984-10-15
Jelena Spasić 1985-01-12
Ivana Marković 1986-11-01
Petar Komnenović 1992-08-08
Oliver Petrović 1993-09-04
Stojan Milić 1995-03-05
Nevena Katić 2000-04-05
		
	
Slika 36. - Rezultat izvršavanja prethodne komande.

Skoro smo gotovi i ostaje samo da povratimo tabelarni prikaz.

Column - tabelarno uređivanje unetog teksta

Program column može se koristiti za uspostavljanje (ili 'povratak') tabelarne strukture teksta (pri čemu je implicirano da je ulazni tekst formatiran tako da svaki red sadrži isti broj kolona, i tako da se u svakoj koloni nalazi podatak istog tipa).

Pri pokretanju sledeće komande ....

		
poslednja_komanda_iz_prethodnog_odeljka | column -t
		
	
Slika 37. - Primer korišćenja komande column za uspostavljanje tabelarne strukture teksta.

.... dobija se sledeći rezultat:

		
Dejan  Kovačević  1981-03-21
Milan  Jovanović  1984-10-15
Jelena Spasić     1985-01-12
Ivana  Marković   1986-11-01
Petar  Komnenović 1992-08-08
Oliver Petrović   1993-09-04
Stojan Milić      1995-03-05
Nevena Katić      2000-04-05
		
	
Slika 38. - Rezultat izvršavanja prethodne komande.

Sledeći koraci ....

Posle čitanja članka, rekli bismo da čitaocima predstoji poveći (ali veoma zabavan, zanimljiv i pre svega koristan), posao otkrivanja dodatnih opcija komandi koje su do sada nabrojane, kao i otkrivanje drugih programa za obradu teksta.

Na primer: da li postoje programi koji su u stanju da preprave proizvoljno formatirani izvorni kod (iz nekog programskog jezika), tako da budu uvaženi određeni obrasci uvlačenja redova i pozicioniranja vitičastih zagrada u odnosu na ostatak koda?!

Saznajte! :)

Pored navedenog - možete se oprobati i u kreiranju sopstvenih programa za obradu teksta (za početak, Python ili Node.js će poslužiti više nego dobro pri realizaciji takvih programa, budući da se bilo koja Python ili Node.js skripta lako može osposobiti da čita standardni ulaz).

U sledećem članku, bavićemo se pisanjem shell skripti za automatizaciju procesa (a upoznaćemo se i sa nekoliko programa o kojima do sada nismo pisali) ....

Autor članka Nikola Vukićević Za web portal codeblog.rs
Napomena: Tekstovi, slike, web aplikacije i svi ostali sadržaji na sajtu codeblog.rs (osim u slučajevima gde je drugačije navedeno) predstavljaju intelektualnu svojinu autora sajta codeblog.rs i zabranjeno je njihovo korišćenje na drugim sajtovima i štampanim medijima, kao i bilo kakvo drugo korišćenje u komercijalne svrhe, bez eksplicitnog pismenog odobrenja autora.
© 2020-2025. Sva prava zadržana.
Facebook LinkedIn Twitter Viber WhatsApp E-mail
početna > Članci > GNU/Linux - 3. deo – Napredne komande
codeBlog codeBlog
Sajt posvećen popularizaciji kulture i veštine programiranja.
Napomena: Tekstovi i slike na sajtu codeblog.rs (osim u slučajevima, gde je drugačije navedeno) predstavljaju intelektualnu svojinu autora sajta codeblog.rs i zabranjeno je njihovo korišćenje na drugim sajtovima i štampanim medijima, kao i bilo kakvo drugo korišćenje u komercijalne svrhe, bez eksplicitnog odobrenja autora.
© 2020-2025. Sva prava zadržana.
Facebook - logo
Instagram - logo
LinkedIn - logo
Twitter - logo
E-mail
Naslovna
   •
Uslovi korišćenja
   •
Obaveštenja
   •
FAQ
   •
Kontakt