REGULÁRIS KIFEJEZÉSEK

A Unix eszközök közül nagyon sok használ mintaillesztést, s a megadott mintára illeszkedõ adatokon további feldolgozást hajt végre.
Vannak olyan parancsok, ahol a felhasználó adja meg a keresendõ mintát, ilyen a grep parancs, másokban rejtve dolgozik a mintakeresõ
algoritmus. Reguláris kifejezések használatakor egy komplex mintát adunk meg (ez a reguláris kifejezés), és azt vizsgáljuk, hogy a
feldolgozandó adatok melyik része illeszkedik a megadott mintára. A reguláris kifejezések karakterekbõl állnak, ezek közül néhány
speciális jelentest hordoz, ezeket metakaraktereknek nevezzük.

A reguláris kifejezéseket meghatározó szabályok:

Példák:
d[0-9][^0-9]
[a-z[|\.
[]ab]
^[0-9]
^[^0-9]*$
 
 

SZÛRÕK
 

1. grep

Arra szolgál, hogy egy adott minta elõfordulását keresse a paraméterként megadott állományokban.
Általános formája:

$ grep mit_keressen hol_keressen
 

Példák.

$ grep '[tf]arka' fajl
- kiírja a fal nevû állomány azon sorait, amelyekben a tarka vagy farka szavak szerepelnek

$ grep '^\^' kalap
- kiírja az összes olyan sort a kalap nevû állományból, amely ^ karakterrel kezdõdik

$ ls -l | grep ^d
- kiírja a munkakönyvtárban levõ összes katalógust

$ grep '^main' *.c
- kiírja a .c végû állományok azon sorait, amelyek a main karaktersorral kezdõdnek
 

2. egrep

Lehetõség van arra, hogy a mintát egy állományból vegyük. Akkor érdemes ezt a lehetõséget használni, ha bonyolult mintát kell gyakran használni.

Példa.

$ cat >pattern
'[A-Z].*[\.!\?]$'
CTRL-D
$ egrep -f pattern fal
 

3. fgrep

karakterláncot párhuzamosan keres
 

4. sort

Bemenetet soronként ASCII kódok szerint rendezi.
-f a kis és nagybetûk megkülönböztetése nélkül rendez
-d szótári rend
-r minden összehasonlítás értelmét az ellenkezõjére fordítja
-u az egymás után következõ egyforma sorok közül csak egyet hagy
 
 

5. AZ awk MINTAKERESÕ ÉS FELDOLGOZÓ NYELV
 

HASZNÁLATA:

$ awk 'program' fájlnevek
 

A program szerkezete:

minta {tevékenység}
minta {tevékenység}

Az awk a fájlnevekben levõ bemenetet soronként beolvassa. Minden sort minden mintával összehasonlít. A sorral egyezõ mintára végrehajtja a hozza tartozó tevékenységet. Nem változtatja meg a bemeneti fájlokat. A minta is, a tevékenység is opcionális. Ha a tevékenységet elhagyjuk, az alapértelmezés szerinti tevékenység az egyezõ sorok kiírása.

pl.
$ awk '/^a/ {print}' file
- kiírja a file nevû állomány minden olyan sorát, amelyik a-val kezdõdik

$ awk '/^a/' file
- az eredmény ugyan az
 

MEZÕK

Az awk minden bemenõ sort automatikusan mezõkre, azaz alapértelmezés szerint szóközökkel vagy tabulátorokkal elválasztott karakterláncokra oszt. Az awk a mezoõket $1, $2, ..., $NF nevekkel jelöli. $0 a teljes sor, változtatás nélkül. NF a mezõk száma.

pl.
$ who | awk '{print $1, $5}'

A mezõelválasztó karaktert meg lehet változtatni a -F parancsopcióval.

pl.
$ who | awk -F: '{print S1}'
 

KIÍRÁS

Az awk a bemeneti mezõk számán kívül más mennyiségeket is nyomom követ. Az NR beépített változó az aktuális bemeneti rekord vagy sor sorszamat adja meg.

$ awk '{print NR, $0}'
- kiírja a teljes sort és elõtte a sor sorszamat

A print utasításban a vesszõkkel elválasztott tételek a kimeneti mezõelválasztó karakter, alapértelmezésben szóköz által elválasztva kerülnek kiírásra. A C nyelvbõl ismert printf utasítással tetszés szerint vezérelhetjük a kimenetet.
 

MINTÁK

A minták lehetnek reguláris kifejezések. Ezen kívül más módon is megadhatunk egy mintát:
pl.
$2 == "a"        - a második mezõ az a karaktert tartalmazza
$2 ~ /./         - a második mezõ bármilyen karaktert tartalmazhat
$2 !~ /^a/       - a második mezõ nem kezdõdhet az a karakterrel
length ($2) == 1  - a második mezõ hossza 1

A ~ jel a reguláris kifejezés egyezését, a !~ jel pedig a különbözõséget jelzi.
A minta a ! jellel tagadható:
!($2== "a")

pl.
Adott a /etc/passwd állomány.
1. Írjuk ki minden felhasználó azonosítóját és nevet;
2. Írjuk ki azokat a felhasználókat, akiknek az azonosítójuk 4 karakterbõl áll.

$ awk -F: '{print $1, $5}' /etc/passwd
$ awk -F: 'length($1)==4 {print $1, $5}' /etc/passwd
 

A BEGIN ÉS END MINTÁK

A BEGIN tevékenységeket az awk parancs az elsõ bemenõ sor beolvasása elõtt hajtja végre; a BEGIN-t változók inicializálására, fejléc nyomtatására, vagy az FS változónak érteket adva a mezõelválasztó kijelölésére használjuk.

Az END tevékenységet az awk a bemenet utolsó sorának feldolgozása után hajtja végre.
 

ARITMETIKA ÉS VÁLTOZÓK

Az awk rendelkezik olyan függvényekkel, amelyek a bemenõ adatokkal matematikai mûveleteket végeznek.

pl
Adott az abc nevû fájl:
123 234 345 sdghnfg
876 756 98 kjhk
12 23 435 rthjft

Adjuk össze az elsõ 3 oszlopban levõ számokat:

awk '{ s1 = s1 + $1
       s2 = s2 + $2
       s3 = s3 + $3 }
     END {print s1, s2, s3}' abc

A változókat nem szukaeges deklarálni, alapértelmezés szerint kezdeti értékük 0 illetve üres karaktersor.
 
 

AZ awk BEÉPÍTETT VÁLTOZÓI
 

FILENAME - az aktuális bemeneti fájl
FS       - mezõelválasztó karakter, alapértelmezés szerint szóköz és tabulátor
NF       - a bemeneti rekord mezõszáma
NR       - a bemeneti rekordok száma
OFMT     - a kimenõ számok formátuma ( alapértelemezés: %g )
OFS      - kimenõ mezõelválasztó karakter ( alapértelmezés: szóköz )
ORS      - kimeneti rekordelválasztó karakterlánc ( alapért: újsor )
RS       - bemeneti rekordelválasztó karakter (alapért: újsor )
 
 

AZ awk OPERÁTOROK (NÖVEKVÕ PRECEDENCIARENDBEN)

= += -= *= /= %=        - értékadás
||                      - VAGY
&&                      - ÉS
!                       - a kifejezés értekének tagadása
> >= < <= == != ~ !~    - relációs operatorok, a ~ egyezés, a !~ nemegyezés
semmi                   - karakterlánc-összekapcsolás
+ -                     - összeadás, kivonás
* / %                   - szorzás, osztás, maradék
++ --                   - növelés, csökkentés
 

AZ awk BEÉPÍTETT FÜGGVÉNYEI

cos(kif)                - a kif koszinusa
exp(kif)                - a kif exponenciálisa
getline()               - a következõ bemenõ sort olvassa, 0-át ad vissza, ha fájlvége, 1-et, ha nem
index(s1, s2)           - az s2 helyzete az s1 karakterláncban, 0-at ad vissza, ha nincs benne
int(kif)                - a kif egész része
length(s)               - az s karakterlánc hossza
log(kif)                - a kif természetes logaritmusa
sin(kif)                - a kif szinusza
split(s,a,c)            - az s-t c karakter szerint a[1] ... a[n] mezõkre bontja, visszaadja n-et
sprintf(fmt, ...)       - ...-ot az fmt szerint formázza
substr(s, m, n)         - az s karakterlánc m-edik karakterénél kezdõdõ n karakteres része
 
 

VEZÉRLÉS ELLENÕRZÉS
 

Az if utasítás:

if (feltétel)
  utasítás1
else
  utasítás2

Az else ág elmaradhat.
 

A for utasítás:

for (kif1; feltétel; kif2)
  utasítás
 

A while utasítás:

while (feltétel)
  utasítás
 

A do utasítás:

do
  utasítás
while (feltétel)
 

A break utasítás az õt közrefogó while vagy do ciklusból törtenõ azonnali kilépést okoz.
 

A next utasítás hatására beolvassa a következõ sort és az awk program újra elölrõl kezdi a minta egyezessenek vizsgálatát.
 

Az exit utasítás hatására a vezérlés azonnal az END mintára kerül.
 
 

TÖMBÖK

A tömböket, ugyanúgy mint a változókat nem kell elõre deklarálni, egy tömb méretét csak a gépben elérhetõ tárterület korlátozza.

pl.
a bemenetet fordított sorrendben írja ki:

awk '{line[NR] = $0}
END { for (i=NR; i>0; i--) print line[i]}' $*

Megjegyzés: a shell szamara a $* a parancssor összes argumentumát jelenti.
 

TÁRSTÖMBÖK ( ASSOCIATIVE ARRAY )

Adatfeldolgozásban gyakori feladat a név-értek jellegû adatpárok értékeinek összegzése.
Például az

Aladar   400
Bela     200
Aladar   100
Cecilia  300
Bela     700

bemenetbõl ki akarjuk számolni a nevekhez tartozó összegeket:

Aladar   500
Bela     900
Cecilia  300

Az awk erre egy érdekes módszert ad, a társtömböket. Rendszerint úgy gondoljuk, hogy egy tömb indexe csak egész szám lehet, az awk-ban azonban bármilyen érteket használhatunk tömbindexként.

Ebben az esetben a for utasítás szintakszisa:

for ( változó in tömb ) utasítás

Így az elõbbi feladat megoldása, feltételezvén, hogy a feldolgozandó állomány neve adatok:

awk '
{sum[$1]+=$2}
END {for (name in sum) print name, sum[name] }
' adatok
 
 

FELADATOK

1. Írjuk ki a rendszeridõt a következõ módon:

xx óra yy perc zz másodperc

date | awk '{print $4}' | awk -F: '{print $1, "óra", $2, "perc", $3, "másodperc"}'

(természetesen egy sorba írva)

2. Írjuk ki n állomány tartalmat (ahol n természetes szám) úgy, hogy az egyes állományok sorai fordított sorrendben jelenjenek meg.

awk ' { line[NR] = $0 }
END { for (i=NR; i>0; i--) print line[i] } ' $*

3. Adott n állomány, (n természetes szám). Írjuk ki az állományok tartalmat úgy, hogy:
- az elsõ maradjon változatlanul
- a másodiknál a sorok mezõit fordított sorrendben ( a mezõelválasztó karakter a : )
- a harmadikat változatlanul
- ...

awk '
  BEGIN { i=-1
          fnev=FILENAME
          print "============================================="
          print "Az allomany neve:", FILENAME
        }
        { if (fnev != FILENAME)
          {
            i=-1*i
            print "============================================="
            print "Az allomany neve:", FILENAME
          }
          if (i>0)
            print
          else
          {
            for (j=NF; j>0; j--) printf("%s ", $j)
              printf("\n")
          }
          fnev=FILENAME
        }
  END   { print "=============================================" }
' $*