Go to the first, previous, next, last section, table of contents.


Kimenet megjelenítése

Az egyik leggyakoribb tevékenység a nyomtatás, vagyis a teljes bemenet vagy csak a bemenet egy részének a kinyomtatása. Egyszerű nyomtatás esetén a print-et érdemes használni. Bonyolultabb formázásra és nyomtatásra a printf alkalmas. Mindkét lehetôséget ebben a fejezetben tárgyaljuk.

A print kifejezés

A print kifejezés egyszerű, szabványos formázással nyomtatja ki az eredményt, csak meg kell adni a szövegeket, számokat egy vesszôvel elválasztott listában. A nyomtatás során szóközök választják el a megadott lista elemeit, majd az egészet egy új sor karakter zárja. Egy kifejezés valahogy így néz ki:

print elem1, elem2, ...

Ha akarod, akkor a teljes listát zárójelek közé teheted. A zárójel kötelezô, ha a lista bármely eleme használja a `>' karaktert (összehasonlító operátor), mivel összekeverhetô az átirányítás operátorral (see section A print és a printf kimenetének átirányítása).

A kinyomtatandó elemek lehetnek szöveg vagy szám konstansok, az aktuális rekord mezôi (mint a $1), változók vagy bármilyen awk kifejezés. A numerikus kifejezéseket elôbb szöveggé konvertálja, és csak utána nyomtatja ki.

A print kifejezésnek teljesen szabadon megadhatod, hogy mit nyomtasson ki, de két kivételtôl eltekintve nem tudod befolyásolni, hogy hogyan jelenítse meg az eredményt -- hány számjegyet, exponenciális vagy lebegôpontos formát használjon és így tovább. (A kivételeket két bekezdésben mutatjuk be, see section Kimeneti elválasztó és a section A numerikus adatok formátumának megadása a print esetén.) A megjelenítési forma megadásához a printf kifejezést kell használni (see section Nyomtatás a printf kifejezéssel).

Az önmagában álló `print' kifejezés megegyezik a `print $0' kifejezéssel: kinyomtatja a teljes rekordot. Egy üres sor nyomtatásához a `print ""' kifejezést kell használni, ahol a "" egy üres szöveg.

Egy adott szöveget szöveg konstansként érdemes kinyomtatni. Ha elfelejted megadni a macskakörmöket, akkor a szavak mint awk kifejezések lesznek kezelve, és a program valószínűleg hibát fog jelezni. Emlékezz arra is, hogy minden elem közé egy extra szóközt is nyomtat.

Minden print kifejezés legalább egy sort nyomtat, persze lehet hogy többet is. Ha egy szöveg tartalmazza az új sor karaktert, akkor azt is kinyomtatja, vagyis a szöveg többi részét egy új sorba nyomtatja ki. Egy print kifejezés tetszôleges számú sort nyomtathat ki.

Példák a print kifejezéssel

Az elsô példa bemutatja a beágyazott új sor karakterek nyomtatását (a `\n' escape szekvencia az új sor karaktert reprezentálja; see section Escape szekvenciák):

$ awk 'BEGIN { print "line one\nline two\nline three" }'
-| line one
-| line two
-| line three

A második példa minden bemeneti rekordból kinyomtatja az elsô két mezôt egy szóközzel elválasztva:

$ awk '{ print $1, $2 }' inventory-shipped
-| Jan 13
-| Feb 15
-| Mar 15
...

Gyakori hiba a print használata során, hogy nem teszünk vesszôt az elemek közé. Ennek az a hatása, hogy közvetlenül egymás után írja ki az elemeket, mivel ez az írásmód az awk-ban az összefűzést jelenti. Tehát ugyanaz a példa vesszôk nélkül:

$ awk '{ print $1 $2 }' inventory-shipped
-| Jan13
-| Feb15
-| Mar15
...

Ha valaki nem ismeri az `inventory-shipped' file tartalmát, akkor a fenti példák eredményei nem mondanak túl sokat. Ilyenkor jól jöhet egy fejléc, jelezve, hogy az elsô mezô a hónap ($1) a második mezô ($2) pedig a zöld rekeszek száma. A fejlécet a BEGIN mintán belül nyomtatjuk ki, hogy csak egyszer jelenjen meg (see section A BEGIN és az END speciális minták):

awk 'BEGIN {  print "Hónap Rekesz"
              print "----- ------" }
           {  print $1, $2 }' inventory-shipped

Kitalálod, hogy mi fog történni? A program futtatása után ezt kapjuk:

Month Crates
----- ------
Jan 13
Feb 15
Mar 15
...

Az adatok és a fejléc nem kerül egy oszlopba! A probléma persze megoldható ha megfelelô számú szóközt teszünk a mezôk közé:

awk 'BEGIN { print "Hónap Rekesz"
             print "----- ------" }
           { print $1, "     ", $2 }' inventory-shipped

Könnyű elképzelni, hogy több oszlop igazítása ezzel a módszerrel elég bonyolult lehet. Kettô vagy három oszlop esetén a szóközök még könnyen kiszámolhatók, de több oszlop esetén könnyű eltéveszteni. Ezért találták ki a printf kifejezést (see section Nyomtatás a printf kifejezéssel), aminek az egyik specialitása az oszlopok igazítása.

Mellékesen, egy print vagy printf kifejezés folytatható a következô sorban, ha a vesszô után egy új sor karakter áll (see section awk kifejezések és sorok).

Kimeneti elválasztó

Ahogy azt korábban leírtuk, a print kifejezés argumentumait vesszô választja el. Ennek hatására a kinyomtatás során az elemek között egy szóközt nyomtat. Ennek persze nem kell így lennie; a szóköz csak az alapbeállítás. Bármilyen karaktersorozat megadható, mint kimeneti mezôelválasztó, az OFS beépített változónak. A változó kezdeti értéke a " " szöveg, egy szóköz.

Egy teljes print kifejezés kimenete egy kimeneti rekord. Minden print kifejezés kinyomtat egy kimeneti rekordot, majd egy szöveget amit úgy hívnak, hogy kimeneti rekordelválasztó, az ORS beépített változóban megadott értéket. Az ORS kezdeti értéke a "\n", az új sor karakter; így alapesetben minden print kifejezés egy új sorral zárja a rekordot.

Természetesen megváltoztathatod, hogy a kimeneti rekordok és mezôk hogyan legyenek elválasztva, ha új értéket adsz az OFS és/vagy ORS változóknak. Ezt általában a BEGIN szabályban érdemes megtenni, (see section A BEGIN és az END speciális minták), a bemenet feldolgozásának megkezdése elôtt. A változókat beállíthatod a parancssorból is a bemeneti file-ok elôtt vagy a `-v' parancssori opció használatával (see section Command Line Options).

Az alábbi példa kinyomtatja az elsô és a második mezôt egy pontos vesszôvel elválasztva és a rekordok közé egy új, üres sort illesztve:

$ awk 'BEGIN { OFS = ";"; ORS = "\n\n" }
>            { print $1, $2 }' BBS-list
-| aardvark;555-5553
-| 
-| alpo-net;555-3412
-| 
-| barfly;555-7685
...

Ha az ORS nem tartalmaz egy új sor karaktert, akkor minden kimenet egy sorba lesz kinyomtatva, kivéve persze ha valami más explicit módon nincs megadva az új sor karakter nyomtatása.

A numerikus adatok formátumának megadása a print esetén

Amikor a print kifejezéssel egy számot nyomtatunk ki, az awk átalakítja a számot szöveggé, majd ezt a szöveget nyomtatja ki. Az awk az sprintf függvényt használja a konvertáláshoz (see section Szövegmanipuláló beépített függvények). Egyelôre elég annyit elmondani, hogy az sprintf úgynevezett formátumleírót használ, ami megadja, hogy a szám (vagy szöveg) hogyan fog megjelenni. A különbözô formátumokat részletesen tárgyaljuk egy késôbbi alfejezetben, section Formátumleíró betűk.

Az OFMT beépített változó tartalmazza az alap formátumleírót, amit a print használ a számok szöveggé konvertálása során. Az OFMT alapértéke "%.6g". Ha más értéket adunk meg az OFMT-nek, akkor szabályozható, hogy a számokat hogyan nyomtassa ki a print. Egy rövid példa:

$ awk 'BEGIN {
>   OFMT = "%.0f"  # minden számot integerként nyomtat ki
>   print 17.23 }'
-| 17

A POSIX szabvány szerint az awk viselkedése nem definiált, ha az OFMT nem lebegôpontos formátumleírót tartalmaz (s.s.).

Nyomtatás a printf kifejezéssel

Ha a print lehetôségeinél jobban akarod kontrollálni a nyomtatási formátumot, akkor a printf kifejezést használd. A printf -el megadhatod a nyomtatási szélességet minden elemre és a számokat különbözô formátumban (különözô számrendszerben, exponenciális vagy lebegôpontos alakban, megadott számjegy pontossággal) nyomtathatod ki. Mindezt egy formátumszöveg megadásával érheted el.

A printf bemutatása

A printf kifejezést így kell használni:

printf formátum, elem1, elem2, ...

Az argumentumokat zárójelek közé is teheted. A zárójel kötelezô, ha bármelyik elem a `>' összehasonlító operátort tartalmazza, mert az awk összekeverheti az átirányítás operátorral (see section A print és a printf kimenetének átirányítása).

A printf és a print közötti különbség a format argumentum. Ez egy szöveg értékű kifejezés; megadja, hogy a többi argumentumot hogyan nyomtassa ki. A kifejezést formátumszövegnek hívják.

A formátumszöveg nagyon hasonló az ANSI C-ben használt printf függvény argumentumához. A format kifejezés jelentôs része egyszerű szöveg, amit csak ki kell nyomtatni. A szöveg között vannak elszórva a formátumleírók. Minden elemhez tartozik egy. A formátum szöveg veszi a következô argumentumot, és az adott helyen kinyomtatja.

A printf kifejezés nem kezd új sort a nyomtatás végén automatikusan. Csak annyit és azt nyomtat ki, amit a formátumszöveg megad, így ha egy új sor karakter is kell a szöveg végére, akkor azt explicit módon kell megadni. Az OFS és az ORS változóknak nincs hatása a printf kifejezésre, így:

BEGIN {
   ORS = "\nOUCH!\n"; OFS = "!"
   msg = "Don't Panic!"; printf "%s\n", msg
}

A program még mindig csak annyit nyomtat ki, hogy `Don't Panic!'.

Formátumleíró betűk

Egy formátumleíró a `%' karakterrel kezdôdik és egy betűvel végzôdik. (Ha csak a `%' karaktert akarod kinyomtatni, akkor a `%%' karaktersorozatot kell használni.) A formátumleíró betű határozza meg a kinyomtatandó adat típusát. A leíró többi része csak módosítja a megjelenést, mint például a nyomtatási szélességet.

Itt egy lista a formátumleíró betűkrôl:

c
Ez egy ASCII karaktert nyomtat ki. A számokat is átkonvertálja ASCII karakterré, így a `printf "%c", 65' kifejezés a nagy `A' betűt nyomtatja ki. Egy szöveg esetén az elsô karaktert nyomtatja ki.
d
i
A két betű megegyezik, mindkettô egy decimális egészt (integer) nyomtat ki. A `%i' az ANSI C-vel kompatíbilis formátumleíró betű.
e
E
Ez egy exponenciális alakú számot nyomtat ki. Például,
printf "%4.3e\n", 1950
`1.950e+03' -t fog kinyomtatni, négy értékes jegyre, amibôl három számjegy a tizedes pont után áll. A `4.3' egy leíró módosító és késôbb tárgyaljuk. A `%E' egy nagy `E' betűt használ a számban a kis `e' betű helyett.
f
Ez egy lebegôpontos számot nyomtat ki, például:
printf "%4.3f", 1950
`1950.000' -t jeleníti meg négy értékes jegyre, amibôl három számjegy a tizedes pont után áll. A `4.3' egy leíró módosító és késôbb tárgyaljuk.
g
G
Ez vagy exponenciális vagy lebegôpontos alakban nyomtatja ki a számot, amelyik a rövidebb azt használja. Ha exponenciális alakot használ, akkor a `%G' egy nagy `E' betűt nyomtat a számban a kis `e' betű helyett.
o
Ez egy elôjel nélküli, oktális, egész számot (integer) nyomtat ki. (Oktális módban, vagy nyolcas alapú számrendszerben, a számjegyek `0' és `7' közöttiek lehetnek; a decimális nyolc oktális alakban `10' lesz.)
s
Kinyomtatja az adott szöveget.
x
X
Ez egy elôjel nélküli, hexadecimális, egész számot (integer) nyomtat ki. (Hexadecimális módban, vagy 16-os alapú számrendszerben a számjegyek `0-9' és `a-f' közöttiek lehetnek. A hexadecimális `f' a decimális 15-nek felel meg.) A `%X' használata esetén a nagy `A' és `F' közötti betűket fogja használni.
%
Ez nem igazán formátumleíró betű, de ha a `%' karakter után áll, akkor a `%%' karaktersorozat hatására egy `%' karaktert fog megjeleníteni. Nem használja a printf argumentumait, és minden leíró módosítót figyelmen kívül hagy.

Amikor az egész (integer) formátumleíró betűt használjuk egy olyan értéknél, ami nem reprezentálható a C long típussal, akkor a gawk automatikusan a `%g' formázási módba kapcsol. Más awk verziók valótlan értéket nyomtathatnak, vagy valami furcsa dolgot csinálhatnak ebben az esetben (s.s.).

A printf formátum módosítói

A formátum leírók módosító komponenseket is tartalmazhatnak, amelyek meghatározzák, hogy az elembôl mennyi jelenik meg. A módosító komponenseket a `%' karakter és a formátumleíró betű között kell elhelyezni. Az alábbi példákban a "*" jelet használjuk a szóközök helyén a kimenetben. A módosítók az alábbi felsorolás sorrendjében jelenhetnek meg:

-
A mínusz jel balra igazítja az argumentumot a megadott szélességen belül (lásd lent). Általában az argumentumok jobbra igazítva jelennek meg. Így,
printf "%-4s", "foo"
ezt adja eredményül: `foo*'.
szóköz
Numerikus konverzió esetén, ha a szám pozitív egy szóköz, ha negatív akkor egy mínusz karaktert nyomtat ki.
+
A plusz jel hatására a számok elôtt mindig fog elôjelet nyomtatni még akkor is ha a szám pozitív. A szélesség megadásával együtt lehet használni és erôsebb mint a szóköz módosító (lásd fent).
#
Bizonyos formátumok esetén egy "alternatív formát" használ. A `%o' esetén a szám elôtt egy zérus számjegy karaktert nyomtat. Ha az `%x' vagy `%X' formátumot használjuk, akkor a nem zérus számok elôtt egy `0x' vagy egy `0X' szöveget nyomtat. A `%e', `%E' és `%f' esetén az eredmény mindig tartalmaz egy tizedes pontot, míg a `%g' és `%G' esetén a szám végén álló zérus karaktereket is mindig kinyomtatja.
0
Egy kezdô zérus karakter azt adja meg, hogy a hely kitöltéséhez zérus számjegy karaktereket használjon a szóközök helyett. Ez a nem numerikus értékekre is igaz (s.s.). Ennek csak akkor van hatása, ha a nyomtatási szélesség nagyobb mint a kinyomtatandó adat szélessége.
szélesség
Ez a szám megadja a kívánt minimális nyomtatási szélességet. Egy szám a `%' karakter és a formátumleíró betű között megnöveli a minimális nyomtatási szélességet. Alapesetben a szóközöket a bal oldalon helyezi el. Például,
printf "%4s", "foo"
eredménye: `*foo'. A szélesség a minimumot adja meg és nem a maximumot. Így ha a kinyomtatandó elem szélesebb mint a megadott érték ettôl függetlenül az egész elemet kinyomtatja, például:
printf "%4s", "foobar"
eredménye: `foobar'. A szélesség elôtti mínusz jel hatására az extra szóközöket a jobb oldalra rakja.
.pontosság
Ez a szám a pontosságot adja meg. Az `e', `E' és `f' formátum esetén a tizedes pont után álló számjegyek számát adja meg. A `g' és a `G' formátumnál az értékes jegyek számát határozza meg. A `d', `o', `i', `u', `x' és `X' formátumoknál a minimálisan kinyomtatandó számjegyek számát, míg egy szövegnél a maximálisan kinyomtatandó karakterek számát írja elô. Így,
printf "%.4s", "foobar"
eredménye: `foob'.

A C programozási nyelv printf kifejezésében használható dinamikus szélesség és pontosság meghatározás ("%*.*s") az awk-ban is engedélyezett. Ebben az esetben nem a formátum szövegben kell megadni a szélesség és/vagy pontosság értékét, hanem mint argumentum kell átadni a kifejezésnek, például:

w = 5
p = 3
s = "abcdefg"
printf "%*.*s\n", w, p, s

pontosan ugyanaz, mint

s = "abcdefg"
printf "%5.3s\n", s

Mindkét program a `**abc' kifejezést nyomtatja ki.

Az awk korábbi verziói nem támogatták ezt a lehetôséget. Ha ilyen awk-ot kell használnod, akkor az összefűzés operátorral szimulálhatod a dinamikus módot:

w = 5
p = 3
s = "abcdefg"
printf "%" w "." p "s\n", s

Bár nem egyszerű olvasni ezt a formát, de működik.

A C programozók már hozzászokhattak a `l' és `h' megadásához a printf formátumszövegében, de az awk-ben ezek nem használhatók. A legtöbb awk implementáció csendben figyelmen kívül hagyja ezeket a módosítókat. Ha a `--lint' opció meg van adva a parancssorban (see section Command Line Options), akkor a gawk figyelmeztet ezen módosítók használata esetén. Ha a `--posix' opció van megadva, akkor használatuk végzetes hiba, a program azonnal leáll.

printf példák

Ez a példa egy igazított táblázatot nyomtat ki a printf segítségével:

awk '{ printf "%-10s %s\n", $1, $2 }' BBS-list

kinyomtatja a `BBS-list' file-ban található rendszerek nevét ($1) egy tíz karakter szélességű mezôbe, balra igazítva. Ezenkívül kinyomtatja a telefonszámot ($2) is. Az alábbi két oszlopból álló táblázat az eredmény:

$ awk '{ printf "%-10s %s\n", $1, $2 }' BBS-list
-| aardvark   555-5553
-| alpo-net   555-3412
-| barfly     555-7685
-| bites      555-1675
-| camelot    555-0542
-| core       555-2912
-| fooey      555-1234
-| foot       555-6699
-| macfoo     555-6480
-| sdace      555-3430
-| sabafoo    555-2127

Észrevetted, hogy a telefonszámot nem mint számot nyomtattuk ki? A telefonszámokat mint szöveg kellett kinyomtatni, mivel szerepel egy mínusz jel a számban. Ha mint számot nyomtatjuk ki, akkor csak az elsô három számjegyet kapnánk meg eredményül, `555'.

A telefonszám formátumánál nem adtunk meg szélességet, mivel az utolsó elem a sorban, így nem akarunk szóközöket utána.

A táblázatot szebbé tehetjük, ha egy fejlécet adunk az oszlopok tetejéhez. Ehhez a BEGIN mintát kell alkalmazni (see section A BEGIN és az END speciális minták), mivel így csak egyszer, az awk program legelején nyomtatja ki a fejlécet:

awk 'BEGIN { print "Név       Szám"
             print "---       ----" }
     { printf "%-10s %s\n", $1, $2 }' BBS-list

Észrevetted, hogy a print és printf kifejezéseket is használtunk a fenti példában? Használhatunk csak printf kifejezést is:

awk 'BEGIN { printf "%-10s %s\n", "Név", "Szám"
             printf "%-10s %s\n", "---", "----" }
     { printf "%-10s %s\n", $1, $2 }' BBS-list

Mivel ugyanazt a formátumot használtuk a fejléc és az adatok nyomtatására, így biztosak lehetünk benne, hogy megfelelôen lesznek igazítva.

Ha hangsúlyozni akarjuk, hogy ugyanazt a formátumot kell használni mindegyik esetben, akkor a formátumot egy változóban is tárolhatjuk:

awk 'BEGIN { format = "%-10s %s\n"
             printf format, "Név", "Szám"
             printf format, "---", "----" }
     { printf format, $1, $2 }' BBS-list

Most már tudod, hogyan kellett volna használni a printf kifejezést az `inventory-shipped' file-ból nyert táblázat nyomtatásánál (see section A print kifejezés). Meg tudod csinálni?

A print és a printf kimenetének átirányítása

Eddig csak azokkal az esetekkel foglalkoztunk, amikor a nyomtatás a szabványos kimeneten, általában a terminálon jelent meg. A print és a printf is képes a kimenetet átirányítani.

Az átirányítást a print vagy a printf kifejezés után kell írni és a formája ugyanolyan, mint a shell-ben használt átirányítás.

Az átirányításnak három formája van: kimenet egy file-ba, kimenet hozzáfűzése egy file-hoz és kimenet átirányítása egy csôvön (pipe-on) keresztül egy másik parancsba. A print kifejezéssel mutatjuk be az átirányítás használatát, de ugyanígy minden érvényes a printf kifejezésre is.

print elemek > output-file
Az átirányítás ezen formája az output-file file-ba nyomtatja az eredményt. Az output-file név bármilyen kifejezés lehet, az értékét átalakítja szöveggé, és ezt használja mint a file neve (see section Kifejezések). Ebben az esetben az output-file file-t elôször letörli és csak utána kezd el az új, üres file-ba nyomtatni. További átirányítások a output-file file-ba már nem törlik a file-t, hanem hozzáfűzik a kimenetet. Ha az output-file file nem létezik, akkor létrehozza. Például az alábbi awk program a BBS neveket a `name-list' file-ba írja, míg a telefonszámokat a `phone-list' file-ba. Minden név vagy szám egy külön sorba kerül.
$ awk '{ print $2 > "phone-list"
>        print $1 > "name-list" }' BBS-list
$ cat phone-list
-| 555-5553
-| 555-3412
...
$ cat name-list
-| aardvark
-| alpo-net
...
print elemek >> output-file
Ebben az esetben a kimenetet egy már létezô output-file file tartalmához fűzi hozzá. A különbség az egyszerű átirányítás (lásd fent) és e forma között az, hogy a file tartalma (ha van) az utóbbi esetben nem törlôdik. Ha az output-file file nem létezik, akkor az awk létrehozza.
print elemek | parancs
Lehetôség van arra is, hogy a kimenetet egy másik programnak adjuk át egy csövön (pipe) keresztül. Ebben az esetben az awk megnyitja a csövet a parancs felé, majd az elemeket kiírja a csôbe. A parancs átirányítási argumentum egy awk kifejezés. Az értékét egy szöveggé alakítja, ami megadja a végrehajtandó shell parancsot. Az alábbi példa két file-t hoz létre, a BBS nevek egy rendezetlen és egy ábécé sorrendben visszafelé rendezett listáját:
awk '{ print $1 > "names.unsorted"
       command = "sort -r > names.sorted"
       print $1 | command }' BBS-list
A rendezetlen listát egy normál átirányítással írjuk ki, míg a rendezést a sort segédprogram végzi el, ami egy csövön keresztül kapja az adatokat. A következô példa átirányítással küld egy üzenet a `bug-system' levelezési listára. Ilyen program hasznos lehet ha a rendszer adminisztrációra használt awk program hibát talál valahol.
report = "mail bug-system"
print "Awk script failed:", $0 | report
m = ("at record number " FNR " of " FILENAME)
print m | report
close(report)
Az üzenetet összefűzéssel készíti el, és az m változóban tárolja, majd egy csövön keresztül a mail programnak küldi tovább. A close függvény alkalmazása fontos, mivel ez lezárja a kimeneti csövet. See section Bemeneti és kimeneti file-ok és csövek lezárása.. A példa azt is bemutatja, hogy hogyan használhatunk egy változót a file vagy a parancs reprezentálására. A változók azért is hasznosak, mert egyébként minden alkalommal pontosan ugyanúgy kellene leírni a hosszú szövegeket.

A `>', `>>' vagy `|' átirányítás arra kéri a rendszert, hogy nyisson meg egy file-t vagy csövet, de csak akkor, ha az adott file-t vagy parancsot még nem használta a program vagy ha az utolsó használat végén le lett zárva.

Mint ahogy azt már korábban írtuk (see section Összefoglaló a getline változatairól), néhány awk implementáció csak egy csô (pipe) megnyitását engedélyezi. A gawk-ban nincs ilyen korlátozás, annyi csövet lehet megnyitni, amennyit az operációs rendszer engedélyez.

Speciális file nevek gawk-ban

Hagyományosan egy program összesen három karakterfolyamot (stream-et) használ beolvasásra és kiírásra. Ezek a szabványos bemenet, szabványos kimenet és a szabványos hibakimenet, amelyek általában a terminálodhoz kapcsolódnak, de gyakran a shell átirányítja ôket a `<', `<<', `>', `>>', `>&' és a `|' operátorok valamelyikével. A szabványos hibakimenet a hibaüzeneteket jeleníti meg; azért van két különbözô karakterfolyam, a szabványos kimenet és a szabványos hibakimenet, mert így külön-külön lehet ôket átirányítani.

Néhány awk implementáció esetén az egyetlen lehetôség egy awk programban a hibaüzenetek megjelenítésére a szabványos hibakimeneten keresztül az alábbi módszer:

print "Serious error detected!" | "cat 1>&2"

Ez úgy működik, hogy egy csövet nyit meg egy olyan shell parancs felé, amelyik el tudja érni a szabványos hibakimenetet. A szabványos hibakimenet értékét az awk-tól veszi át. Ez a megoldás nem elegáns és nem is hatékony, mivel egy másik programot kell indítani. Így az emberek jelentôs része nem ezt a módszert használja, helyette a hibaüzeneteket a terminálra küldi, például így:

print "Serious error detected!" > "/dev/tty"

Általában ennek ugyanaz a hatása, de nem mindig: habár a terminál a szabványos hibakimenet az esetek nagy részében, de át lehet irányítani, és ebben az esetben a terminálra írás nem jó megoldás. Ráadásul ha az awk a háttérben fut, akkor nincs is terminál hozzárendelve, és a `/dev/tty' megnyitása nem lesz sikeres.

A gawk speciális file neveket biztosít a három alap karakterfolyam eléréséhez. Ha a kimenetet vagy a bemenetet átirányítjuk, és a file neve megegyezik valamelyik speciális névvel, akkor a gawk az adott karakterfolyamot fogja használni.

`/dev/stdin'
A szabványos bemenet (0 file leíró).
`/dev/stdout'
A szabványos kimenet (1 file leíró).
`/dev/stderr'
A szabványos hibakimenet (2 file leíró).
`/dev/fd/N'
Az N file leírónak megfelelô file. Ezeket a file-okat az awk-ot elindító programnak kell megnyitnia (általában a shell). Ha csak nem bravúroskodsz, akkor csak a 0, 1 és a 2 file leírók állnak rendelkezésre.

A `/dev/stdin', `/dev/stdout' és `/dev/stderr' file-ok megegyeznek a `/dev/fd/0', `/dev/fd/1' és `/dev/fd/2' file-okkal sorrendben, de a nevük kifejezôbb.

A helyes módszer egy hiba megjelenítésére egy gawk programból a `/dev/stderr' használatával:

print "Serious error detected!" > "/dev/stderr"

A gawk olyan speciális file-ok elérését is biztosítja, amelyek az éppen futó gawk-ról adnak információt. Minden ilyen "file" csak egy rekordnyi információt tartalmaz. Ha többször akarod kiolvasni az értékét, akkor elôbb le kell zárni a close függvénnyel (see section Bemeneti és kimeneti file-ok és csövek lezárása.). A file-ok:

`/dev/pid'
A file olvasása esetén visszaadja a futó program azonosítóját (ID) decimális számként egy új sor karakterrel lezárva.
`/dev/ppid'
A file olvasása esetén visszaadja a program szülôjének azonosítóját (ID) decimális számként egy új sor karakterrel lezárva.
`/dev/pgrpid'
A file olvasása esetén visszaadja a futó program csoport azonosítóját decimális számként egy új sor karakterrel lezárva.
`/dev/user'
A file olvasása egyetlen rekordot ad vissza egy új sor karakterrel lezárva. A mezôket szóközök választják el. A mezôk jelentése:
$1
A getuid rendszer függvény visszatérési értéke (a valódi felhasználói azonosító, ID).
$2
A geteuid rendszer függvény visszatérési értéke (az effektív felhasználói azonosító).
$3
A getgid rendszer függvény visszatérési értéke (a felhasználó valódi csoport azonosítója).
$4
A getegid rendszer függvény visszatérési értéke (a felhasználó effektív csoport azonosítója).
Ha van, a többi mezô a getgroups rendszer függvény által visszaadott csoport azonosítókat tartalmazza. (Nem minden rendszer támogatja, hogy egy felhasználó több csoportba tartozhat.)

Ezeket a speciális file-okat a parancssorban is lehet használni mint adat file-ok vagy az awk programon belül átirányítással, de nem használhatók mint program file a `-f' opcióval.

"Compatibility" módban (see section Command Line Options) a gawk nem ismeri fel ezeket a speciális file-okat.

Figyelem: Ha a rendszereden nincs `/dev/fd' könyvtár (vagy bármely más fent megadott speciális file), akkor a gawk maga fogja értelmezni a megadott file nevet. Például a `/dev/fd/4' mint kimenet használata esetén a program a 4-es file leíró által megadott file-ba fog írni és nem egy olyan file leíróba ami a 4-es file leíró másolata. Általában ez nem annyira érdekes; de fontos, hogy ne zárjuk le a 0, 1 és 2 -es file leírókat, ugyanis ebben az esetben az awk viselkedése megjósolhatatlan.

A futó awk programról információt adó file-ok lehet, hogy nem lesznek benne a gawk késôbbi verzióiban, see section Probable Future Extensions.

Bemeneti és kimeneti file-ok és csövek lezárása.

Ha többször ugyanazt a file nevet vagy shell parancsot használjuk a getline-al (see section Explicit beolvasás getline-al) egy awk programon belül, a file-t csak az elsô alkalommal nyitja meg (a parancsot csak az elsô alkalommal hajtja végre). Ezzel egy idôben beolvassa az elsô rekordot. A következô alkalommal, amikor ugyanazt a file-t vagy shell parancsot hasnáljuk a getline-al, a következô rekordot olvassa be.

Ugyanez érvényes a csövekre is ha írunk bele; az adott file-ra vagy parancsra emlékszik az awk és az elsô alkalom után mindig ugyanabba a file-ba írja vagy ugyanannak a parancsnak küldi a kimenetet. A file vagy csô addig marad nyitva, amíg az awk ki nem lép.

Ez persze azt jelenti, hogy ha ugyanazt a file-t többször szeretnéd beolvasni az elejétôl vagy ugyanazt a shell parancsot szeretnéd többször lefuttatni, akkor extra lépéseket kell tenned. A close függvényt kell használni:

close(filenév)

vagy

close(parancs)

A filenév vagy parancs argumentum bármilyen kifejezés lehet, de az értéke pontosan ugyanaz kell legyen mint amit a megnyitásnál használtunk (a szóközök és egyéb "extra" karakterek is fontosak). Például ha egy csövet így nyitsz meg:

"sort -r names" | getline foo

akkor bezárni így kell:

close("sort -r names")

Miután ez a függvény lefutott a következô getline, print vagy printf kifejezésnél ugyanazt a file-t újra megnyitja vagy ugyanazt a parancsot újra lefuttatja.

Mivel a lezárásnál ugyanolyan értékű kifejezést kell használni mint a megnyitásnál ezért érdemes a file nevét vagy a parancsot egy változóban tárolni. Az elôbbi példa tehát így fog kinézni:

sortcom = "sort -r names"
sortcom | getline foo
...
close(sortcom)

Ez segít elkerülni a nehezen megtalálható "elgépelési" hibákat az awk programodban.

Az alábbiakban leírunk néhány indokot, hogy a kimenetet miért érdemes/kell lezárni:

A close függvény zérust ad vissza, ha a lezárás sikeres volt, egyébként valamilyen zérustól különbözô értéket. Ebben az esetben a gawk beállítja az ERRNO változót egy, a hibát leíró üzenetre.

Ha több file-t próbálsz megnyitni, mint amit a rendszer engedélyez, akkor a gawk megpróbálja a rendelkezésre álló nyitott file-okat megosztani (multiplex), és az új file-t is megnyitni. Ez a lehetôség az operációs rendszertôl is függ; nem mindig működik, ezért jó programozási szokás és könnyíti a hordozhatóságot ha a file-t mindig lezárod, miután már nem használod.


Go to the first, previous, next, last section, table of contents.