Mintakeresés állományokban

Az előzőek során említettük már a grep programot, amelyik arra szolgál, hogy egy adott minta előfordulásait keresse a paraméterként megadott állományokban.

$ cat semmi

*****

Ez semmi

***** *****

alma

korte

repa

retek

alma

mogyoro

alma

barack

korte

mogyoro

narancs

$ grep a semmi

alma

repa

alma

alma

barack

narancs

A minta, amivel kiválasztottuk a kívánt sorokat egy reguláris kifejezés, jelenleg az a betű. Természetesen dolgozhat a grep mint egy pipeline tagja is.

$ ls -l | grep '^d'

A fenti parancs az ls -l parancs kimenetéről kiválasztja a d betűvel kezdődő sorokat, azaz a katalógusokat, és csak azokat engedi tovább. Sokszor használható ügyes eszköz a grep akkor is, ha az állományaink közt keresünk egyet a tartalma alapján.

$ grep '^main' *.c

A fenti utasítássor a .c kiterjesztésű állományokból az(oka)t a sorokat fogja kilistázni, amely(ek) a main kulcsszóval kezdődnek. A példákból látható, hogy a mintát időnként idézőjelbe tettük, időnként nem. Az idézőjelek használata akkor célszerű, ha a minta a shell által is értelmezett speciális karaktert (pl. *?) is tartalmaz. A grep parancs nem tud minden reguláris kifejezést, mint mintát elfogadni, ezért hasznos ismernünk az egrep parancsot is, ahol logikai kapcsolattal összefűzhetjük a mintákat, ezt jelöli a '|' karakter, tehetünk a minta után '+' jelet, ha a minta egy vagy többszöri előfordulását keressük, illetve '?' jelet, ha a minta legfeljebb egyszeri előfordulását figyeljük.

$ egrep '^main|^\/\*+Ez a foprogram!? \*+\/' *.c

A fenti minta beszédesen úgy hangzik, hogy keressük azt a .c kiterjesztésű állományt, amelyben vagy a main függvény van, vagy egy komment sorban, esetleg csillagok közé zárva, az "Ez a foprogram" szöveget találja, úgy, hogy a végén vagy van, vagy nincs felkiáltójel.

Az egrep-nél lehetőségünk van arra, hogy a mintát egy állományból vegyük. Az ember nyilván akkor használja ezt a lehetőséget, ha bonyolult mintát kell gyakran alkalmazni.

$ cat pattern

[A-Z].*[\.!\?]$

$ egrep -f pattern szoveg

A példánkban a szoveg nevű állományból azokat a sorokat választjuk ki, amelyek (nagy valószínűséggel, mert hisz' tulajdonnévvel is kezdődhet egy sor) legalább egy teljes mondatot tartalmaznak (tehát nagybetűvel kezdődnek és mondatzáró írásjelre végződnek).

Az fgrep (fixed grep) parancs esetében a minta csak karakterlánc lehet (nem reguláris kifejezés!!!)

A grep család tagjai a visszatérési értéket 0-ra állítják, ha nem találtak illeszkedést, 1-re, ha igen, és 2-re, ha akadályoztatva voltak a parancs végrehajtásában.

Míg a grep parancs sorokat választ ki az állományból, addig a cut paranccsal oszlopokat lehet "kiszabni" belőle. Az oszlopokat kétféleképp értelmezi a parancs. Az első, egyszerűbb esetben, karakterpozíció vagy karakterpozíciókkal határolt mező formájában adjuk meg a kivágandó oszlopot, mint a következő példában:

$cut -c1,3-5 semmi

****

E se

****

ama

krte

rpa

rtek

ama

mgyo

ama

brac

krte

mgyo

nran

A másik lehetőségünk, hogyha nem a karakterpozíció szerint, hanem mezőelválasztó karakterek pozíciója szerint meghatározott oszlopokat, ebben az értelemben mezőket választunk ki a sorokból. A mezőelválasztó karaktert a -d opció után írjuk.

$cut -f4,5 -d: /etc/passwd

A fenti példában a /etc/passwd állományból a csoportazonosítót és a teljes nevet tartalmazó mezőket választottuk ki.

Vigyázzunk arra, hogy a cut nem tud megbírkózni a hagyományos unixos szóelválasztás (egy vagy több szóköz vagy tabulátor) fogalmával, mivel egy és csakis egy elválasztó karakter határolhatja el a feldolgozandó mezőket, s ha több egymás utáni szóközt talál, minden egyes szóköz után egy üres mezőt tételez fel. Például ha mintafajlunk az alábbi:

abc 123 456

def 23 456

ghi 3 456

akkor a cut -d' ' -f 2 <mintafajl parancs hatására nem az ösztönösen várt

123

23

3

lesz a kapott eredmény, hanem

123

miután az egynél több szóköz üres mezőket jelentett a cut számára.

A uniq program arra a célra szolgál, hogy az egymás után következő azonos sorokat kiszűrje az inputból, s minden sort csak egyszer írjon a kimenetre. E tulajdonsága miatt gyakran szokták a sort, illetve a grep előtt vagy után, e két program bemenetének vagy kimenetének szűrésére használni.

$ sort semmi | uniq -c

1 *****

1 ***** *****

1 Ez semmi

3 alma

1 barack

2 korte

2 mogyoro

1 narancs

1 repa

1 retek

$

Tovább is ragozhatjuk a kérdést, ha meg akarjuk nézni, hogy melyik sor fordult elő a leggyakrabban.

$ sort semmi | uniq -c| sort -n | tail -1

3 alma

$

A példában újdonságként megjelent a tail parancs, amely az állomány végéből ad vissza sorokat.

A tail paranccsal nagyméretű állományokban tudunk mozogni, így elsősorban arra használjuk, hogy egy hosszú állomány végére pozícionáljunk, s onnan írassunk ki egy darabot. Az alábbi példában a /etc/passwd állomány utolsó 50 karakterét íratjuk ki:

$ tail -50c /etc/passwd

pix

abraham:x:108:1:abraham:/usr/abraham:/bin/ksh

$

Bizonyos Unix implementációkban a tail parancs csak 20 kB mélységig képes visszamenni a listázott fájlban. Ha ennél többet szeretnénk kilistázni (például logfájlokat kurtítanánk, de nem elég a 20 kB méret) akkor célszerű a fájl elejétől elindulni, s a head paranccsal pozicionálni az általunk kívánt részig.

 

Tartalomjegyzék