GNU/Linux - 3. deo – Napredne komande
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 obavljanje operacija 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.
Još nekoliko napomena
Pošto polako počinjemo da se bavimo naprednijim UNIX komandama, želimo da što pravilnije "naštimamo" očekivanja čitalaca, i stoga ćemo se ukratko osvrnuti na određene pojave ....
Pre svega, 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 izdaleka, 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.
U budućnosti, sasvim lako se može desiti 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 kom slučaju je naziv datoteke jedan od argumenata).
Komanda grep poziva se po sledećoj šemi:
$ grep [opcije] obrazac [datoteka]
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
.... a ovoga puta više pažnje ćemo obratiti na primere pretrage teksta koji se učitava direktno iz datoteka.
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
Za početak, pozabavićemo se jednostavnim primerom pretrage, bez regularnih izraza.
Ukoliko upotrebimo sledeću nisku (u svojstvu vrlo jednostavnog 'obrasca') ....
$ grep 'admin' 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
Međutim, ako pokušamo - po istom principu - da pronađemo osobu (ili osobe), pri čemu se kao kriterijum naizgled koristi 'godina rođenja' ....
$ grep '1981' saradnici.txt
.... 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
U jednom redu, uneta niska (zaista) predstavlja godinu rođenja, dok u drugom redu niska predstavlja (samo) deo id-a saradnika.
U konkretnom slučaju koji razmatramo, 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 npr. 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
Zapažamo argument -E (--extended-regexp), preko koga se uključuje upotreba regularnih izraza, 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), a 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.
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
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. (što 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 kompleksniji program awk koji ćemo opisati kasnije u članku (uz odgovarajuće praktične primere).
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", što ćemo dodatno pojasniti preko dosadašnjeg primera ....
U prvom slučaju, tražili smo redove sa podacima o administratorima sajta, a ako bi pored administratora (nivo privilegija 30), bilo potrebno pronaći i moderatore (nivo privilegija 20), i takav zadatak se može obaviti korišćenjem programa grep - pod uslovom da se pažljivo postupa po pitanju toga koji podatak treba koristiti kao kriterijum za pretragu.
Sledeća pretraga ....
$ grep -E 'admin|moderator' saradnici.txt
.... vraća željeni rezultat, ali zato "idejno slična pretraga" nalik na sledeću pretragu ....
$ grep -E '20|30' saradnici.txt
.... 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, 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.
Nešto kasnije, videćemo kako se preko programa awk može rešiti zadatak pronalaženja korisnika čiji je nivo privilegija veći ili jednak 20, ali, na ovom mestu vraćamo se na upoznavanje sa još nekoliko mogućnosti programa grep (nakon čega sledi poglavlje u kome ćemo se upoznati i sa osnovnim mogućnostima programa sed).
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
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
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
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
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
Sed - osnovna obrada teksta
Pošto smo se upoznali sa programom koji praktično predstavlja 'uobičajenu opciju' za pretragu teksta u Linux terminalu, upoznaćemo se i sa programima koji se tipično koriste za izmenu teksta i obavljanje drugih zadataka.
Program sed (Stream Editor), omogućava obavljanje raznovrsnih operacija nad ulaznim niskama, ali, u praksi se najčešće koristi za izmenu delova ulaznog teksta. *
Obrada teksta preko programa sed, izvršava se po sledećoj šemi:
$sed 'operacija/postojeći_obrazac/novi_tekst/' ulazna_datoteka
Komande se zadaju unutar niske, a argument "operacija" označava jednu od mogućih internih komandi za obradu teksta.
Pošto se program sed 'tipično'/najčešće koristi za zamenu delova teksta, pogledajmo za početak upravo jedan takav primer (interna komanda zadata je preko argumenta s koji označava zamenu ("s" - skraćeno od "substitute")):
$ sed 's/saradnik/operator/' saradnici.txt
Nakon izvršavanja komande, sve pojave niske "saradnik" zamenjene su niskom "operator", pri čemu se rezultat prikazuje u terminalu, a 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
Kad smo već kod praktičnosti, naveli smo da se za komplikovanije primere obrade najčešće koristi program awk, međutim, 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
Ako pokrenemo poslednju komandu, zaglavlje se (faktički) preskače, što znači da će pretraga i zamena početi od 3. reda (praktično: 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
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
AWK - napredna manipulacija tekstom
Kombinovanjem jednostavnih programa i tehnika koje smo do sada prikazali (programi grep i sed, redirekcija i sl), moguće je obaviti većinu svakodnevnih zadataka sa tekstom, ali, kada je u pitanju precizna i sveobuhvatna obrada teksta u Linux terminalu, "zvezda večeri" je program AWK.
U najpraktičnijem smislu, 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.
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
.... 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.
Ako se filtracija redova obavlja preko regularnih izraza (u primeru koji razmatramo), biće pretraživani redovi koji počinju cifrom, a blok sa izvršnim komandama, podrazumeva ispis tri specifične kolone:
awk '/^[0-9]/ { printf("%s %s %s\n", $2, $3, $5) }' saradnici.txt
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 (tj. 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 komandeprintf(u pitanju je C-olika sintaksa, što naravno ne čudi, budući da je programawkrazvijen u istoj "softverskoj kuhinji" kao i programski jezik C) - u (internoj) komandi
printf, kao argumenti se koriste specijalne promenljive:$2,$3i$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
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).
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(gdenpredstavlja indeks poslednje kolone)
.... pri čemu su definisane još dve korisne promenljive:
NF(Number of Fields) - ukupan broj polja (tj. kolona) u trenutnom reduNR(Number of Records) - ukupan broj redova
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
.... 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
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
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)
"Da sve bude još bolje", izlaz se lako može pajpovati npr. u program preko koga se standardni ulaz prosleđuje u tekstualni clipboard operativnog sistema:
awk 'prethodni uslovi i printf' datoteka | xclip -selection clipboard
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
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
.... pri čemu se (očekivano) dobija sledeći rezultat:
Milan Jovanović admin
Dejan Kovačević admin
Ivana Marković moderator
U nastavku, razmotrićemo još i dve jednostavne komande za formatiranje izlaza.
Sort - uređivanje redova
Program sort koristi se za uređivanje redova 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
.... 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
.... rezultat se može dodatno sortirati preko komande sort:
awk_prethodni | sort -k 3
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
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).
Nakon pokretanja sledeće komande ....
poslednja_komanda_iz_prethodnog_odeljka | column -t
.... 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
Pred kraj, napravićemo malu digresiju u odnosu na uobičajenije "Linux komande" (s tim da je u pitanju veoma zanimljiva srodna tematika, sa kojom smo se već okvirno upoznali) ....
Obrada standardnog ulaza
U uvodnom članku predstavili smo protočnu obradu (tj. 'pajpovanje') kao jednu od najkorisnijih osnovnih tehnika u UNIX-olikim okruženjima, a na ovom mestu ćemo iskoristiti priliku da se upoznamo i sa time kako se u nekoliko programskih jezika mogu implementirati mehanizmi za 'prihvat i obradu' prosleđenih podataka.
C/C++
U programskom jeziku C, obrada standardnog ulaza obavlja se preko FILE * pokazivača stdin koji je (u najpraktičnijem smislu) direktno povezan sa konzolnim ulazom operativnog sistema.
#include <stdio.h>
#define VELICINA_BAFERA 256
int main()
{
char pajpovani_tekst[VELICINA_BAFERA + 1];
char c;
int i = 0;
while ((c = fgetc(stdin)) != EOF) {
pajpovani_tekst[i] = c;
i++;
}
pajpovani_tekst[i] = 0;
printf("%s", pajpovani_tekst);
return 0;
}
U programskom jeziku C++, isti zadatak obavlja se preko objekta cin.
#include <iostream>
int main(int argc, char *argv[]) {
std::string pajpovani_tekst;
while (!std::cin.eof()) {
std::string linija;
getline(std::cin, linija);
pajpovani_tekst += linija + "\n";
}
std::cout << pajpovani_tekst;
return 0;
}
Node JS (JavaScript)
U okruženju Node.js, objekat process sadrži (pod)objekte sa informacijama o trenutno pokrenutom Node.js procesu, * i pri tom se jedan od podobjekata, stdin, može koristiti za obradu standardnog ulaza. **
let pajpovani_tekst = "";
process.stdin.on("readable", () => {
let deo_teksta;
while ((deo_teksta = process.stdin.read()) !== null) {
pajpovani_tekst += deo_teksta;
}
});
process.stdin.on("end", () => {
process.stdout.write(pajpovani_tekst);
});
Python
U Python-u, za obradu standardnog ulaza koristi se objekat stdin (iz modula sys).
import sys
pajpovani_tekst = ""
while True:
red = sys.stdin.readline()
if not red:
break
pajpovani_tekst += red
print(pajpovani_tekst)
Sledeći koraci ....
Posle čitanja članka, reklo bi se 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.
Pored navedenog - možete se oprobati i u kreiranju sopstvenih programa za obradu teksta, pri čemu će (za početak) Python ili Node.js poslužiti više nego dobro pri realizaciji takvih programa, budući da se bilo koja Python skripta ili Node.js skripta (kao što smo videli u prošlom poglavlju), lako može osposobiti za čitanje standardnog ulaza.
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) ....