A beépített függvények olyan függvények, amelyek mindig az awk
programod rendelkezésére állnak. Ez a fejezet definiálja az awk összes
beépített függvényét; néhányat más bekezdésekben is megemlítettünk már.
(Te is definiálhatsz függvényeket.
See section Felhasználó által definiált függvények.)
Ahhoz, hogy egy beépített függvényt meghívhassunk, a nevét kell leírni,
majd az argumentumait zárójelek között. Például, `atan2(y + z, 1)'
a atan2 függvényt fogja meghívni két argumentummal.
A függvénynév és a nyitó zárójel közötti szóközöket nem veszi figyelembe
az awk, de azt tanácsoljuk, hogy ne használj szóközöket itt.
A felhasználó által definiálható függvények hívásánál a szóközök nem
megengedettek, és ha nem használsz szóköz karaktert a függvénynév és a nyitó
zárójel között, akkor könnyebb ezt a hibát elkerülni.
Minden beépített függvény elfogad egy adott számú argumentumot. Bizonyos
esetekben, az argumentumok elhagyhatók. Hogy mi történik akkor, amikor
egy függvénynek nem adunk meg argumentumot, az függvényről függvényre
változik, és az adott függvénynél ezt bemutatjuk. Néhány awk
implementáció a függvénynek átadott extra argumentumokat
nem veszi figyelembe. Ugyanakkor a gawk esetén, ez az eset egy
végzetes hibát fog generálni.
Amikor egy függvény meghívásra kerül, akkor az argumentumait adó kifejezések először teljesen kiértékelődnek, és csak utána történik meg függvényhívás. Például az alábbi programrészletben:
i = 4 j = sqrt(i++)
a i változó értéke öt lesz mielőtt az sqrt függvény
meghívódik. A függvény argumentuma négy lesz.
A függvény argumentumainak kiértékelési sorrendje nem definiált. Így, nem szabad arra számítani, hogy az argumentumok balról jobbra vagy jobbról balra értékelődnek ki. Például:
i = 5 j = atan2(i++, i *= 2)
Ha a kiértékelés balról jobbra halad, akkor az i értéke először hat
lesz, majd 12 és az atan2 argumentumai hat és 12 lesz. De ha a
kiértékelés jobbról balra halad, akkor az i értéke először 10 lesz,
majd 11, és az atan2 argumentumai 11 és 10 lesz.
Az alábbiakban megadjuk a számokkal dolgozó beépített függvények listáját. Az opciónális argumentumokat szögletes zárójelek veszik körül ("[" és "]").
int(x)
int(3) eredménye három, int(3.9) eredménye három,
int(-3.9) eredménye -3 és int(-3) eredménye szintén
-3.
sqrt(x)
sqrt(4) eredménye kettő.
exp(x)
e ^ x), vagy hibát jelez ha x az értelmezési
tartományon kívül esik. Az x értelmezési tartománya
a géped lebegőpontos ábrázoló képességétől függ.
log(x)
sin(x)
cos(x)
atan2(y, x)
y / x (radián)
inverz tangensét (arctan).
rand()
rand által
visszaadott értékek egyenletesen oszlanak el egy és zérus között.
Az érték viszont soha nem zérus és nem egy.
Gyakran véletlen egész számokra van szükséged. Itt egy felhasználó által
definiálható függvény, ami véletlen, nem negatív, n-nél kisebb
egész számokat generál:
function randint(n) {
return int(n * rand())
}
A szorzás egy zérusnál nagyobb, és n-nél kisebb véletlen valós számot
generál. Ezután egész számmá konvertáljuk (az int függvényt használva),
ami zérus és n - 1 közé esik, a határokat is beleértve.
Itt egy másik példa, ahol hasonló függvényt használunk egy és n közé
eső számok generálására. Ez a program minden bemeneti rekordnál egy új
véletlen számot nyomtat ki.
awk '
# Szimulált kockadobás
function roll(n) { return 1 + int(rand() * n) }
# 3 db hat-oldalú kockával dobunk és
# a dobott pontok összegét nyomtatjuk ki.
{
printf("%d points\n",
roll(6)+roll(6)+roll(6))
}'
Figyelem: A legtöbb awk implementációban,
a gawk-ot is beleértve, a rand függvény ugyanattól a
számtól (seed) kezd el véletlen számokat generálni, amikor
az awk újraindul. Így a program minden alkalommal
ugyanazt az eredményt fogja produkálni. A számok véletlenszerűek
egy awk futtatás alatt, de megjósolhatók egymás utáni futtatások során.
Ez hasznos lehet tesztelésnél, de ha azt akarod, hogy a programod
minden futtatás során más számot generáljon, akkor más kezdő
számot (seed) kell megadni minden alkalommal. Ezt az srand függvénnyel
lehet elérni.
srand([x])
srand függvény a véletlen szám generálás kezdőpontját (seed)
állítja be az x által megadott értékkel.
Minden kezdőpont más véletlen számsorozathoz vezet.(11)
Így ha a kezdőpont ugyanaz egy második alkalommal, akkor ugyanazt a sorozatot
fogod megkapni, mint az első alkalommal.
Ha nem adsz meg argumentumot és csak az srand() formát használod,
akkor az aktuális dátumot és időpontot használja kezdőpontként. Ez a módja
annak, hogy igazi véletlen számokat generáljunk.
Az srand függvény visszatérési értéke az előző kezdőpont értéke.
Ez lehetővé teszi a megadott kezdőpontok nyilvántartását és ugyanazon
véletlen szám sorozatok generálását.
Ebben a bekezdésben található függvények szövegeket vizsgálnak vagy változtatnak meg. Az opcionális argumentumok szögletes zárójelek között ("[" and "]") jelennek meg.
index(in, find)
$ awk 'BEGIN { print index("peanut", "an") }'
-| 3
Ha nem találja a find szöveget, akkor az index függvény
zérussal tér vissza. (Az awk szövegek első karaktere az egyes
pozíciónál található.)
length([string])
length("abcde") visszatérési értéke öt.
Ezzel ellentétben, az length(15 * 35) eredménye három lesz. Miért?
Nos, 15 * 35 = 525, amit szöveggé konvertál "525", amiben három karakter
van.
Ha nincs argumentum megadva, akkor a length függvény a $0
hosszát adja meg.
Az awk régebbi verzióiban a length függvényt zárójelek nélkül
is meg lehetett hívni. A POSIX szabvány ezt "helyteleníti". Ez azt jelenti,
hogy ez a lehetőség végül is el fog tűnni a szabványból. Így a maximális
hordozhatóság érdekében a legjobb a zárójeleket kitenni.
match(string, regexp)
match függvény a string szövegben a leghosszabb,
legbaloldalibb szövegrészletet keresi meg, ami illeszkedik a regexp
reguláris kifejezésre. Azt a karakterpozíciót adja vissza, vagy indexet,
ahol a szövegrészlet kezdődik (ez egy, ha a string elején kezdődik).
Ha nem volt illeszkedés, akkor a visszatérési érték zérus.
A match függvény az RSTART beépített változónak az indexet
adja meg, mint új érték. Ezen kívül az RLENGTH beépített változó
az illeszkedő szöveg hosszát adja meg. Ha nem volt illeszkedés, az
RSTART értéke zérus, az RLENGTH értéke -1 lesz.
Például:
awk '{
if ($1 == "FIND")
regex = $2
else {
where = match($0, regex)
if (where != 0)
print "Match of", regex, "found at", \
where, "in", $0
}
}'
Ez a program olyan sorokat keres, amelyek illeszkednek a regex változóban
tárolt kifejezésre. Ez a reguláris kifejezés megváltoztatható, így ha a sorban
az első szó a `FIND', akkor a regex új értéke a sor második szava lesz.
Így ha ez a bemenet:
FIND ru+n My program runs but not very quickly FIND Melvin JF+KM This line is property of Reality Engineering Co. Melvin was here.az
awk ezt fogja kinyomtatni:
Match of ru+n found at 12 in My program runs Match of Melvin found at 1 in Melvin was here.
split(string, array [, fieldsep])
array[1] -ba teszi, a másodikat a array[2]-ba
és így tovább. A harmadik argumentum, a fieldsep, egy reguláris kifejezés
ami azt adja meg, hogy hol kell a string szöveget felvágni (ugyanúgy mint
ahogy az FS azt adja meg, hogy hol kell a mezőket feldarabolni).
Ha a fieldsep nincs megadva, akkor az FS értékét használja.
A split függvény visszatérési értéke a generált szöveg darabok száma.
A split függvény a bemeneti rekord mezőkre darabolásához hasonló módon
vágja fel a szöveget. Például:
split("cul-de-sac", a, "-")
felvágja a `cul-de-sac' szöveget három darabba a `-' jel mentén.
Az a tömb tartalma a következő lesz:
a[1] = "cul" a[2] = "de" a[3] = "sac"A
split függvény visszatérési értéke három lesz.
Ugyanúgy mint a meződarabolásnál, amikor a fieldsep értéke " ",
akkor a kezdő és záró szóközöket és tab karaktereket nem veszi figyelembe és
az elemeket szóközök és tab karakterek (sorozatai) választhatják el.
Szintén igaz, hogy ha a fieldsep értéke egy üres szöveg, akkor a szöveg
minden karaktere egy külön tömb elembe kerül. (Ez egy gawk
specifikus kiterjesztés.)
Az awk újabb implementációi, a gawk is, megengedi, hogy
a harmadik argumentum egy regexp konstans (/abc/) vagy egy szöveg
legyen (s.s.). A POSIX szabvány szintén megengedi ezt.
Mielőtt a szöveget felvágná, a split függvény kitörli az array
tömb minden létező elemét (s.s.).
Ha a string szöveg egyik részlete sem illeszkedik a fieldsep
szövegre, akkor az array tömbnek csak egy eleme lesz. Az elem
értéke maga az eredeti szöveg, a string, lesz.
sprintf(format, expression1,...)
printf függvény nyomtatna ki ugyanazokkal az argumentumokkal
(see section Nyomtatás a printf kifejezéssel).
Például:
sprintf("pi = %.2f (approx.)", 22/7)
a visszatérési értéke a "pi = 3.14 (approx.)" lesz.
sub(regexp, replacement [, target])
sub megváltoztatja a target értékét. A függvény a
regexp reguláris kifejezésre illeszkedő legbaloldalibb, leghosszabb
illeszkedést keresi a target-en belül. Ezután az egész szöveget
megváltoztatja úgy, hogy az illeszkedő szöveg részletet lecseréli a
replacement szövegre. A módosított szöveg lesz a target
új értéke.
Ez a függvény különleges, mert a target értékét nem csak egy új
érték "kiszámításához" használja, hanem meg is változtatja.
Csak bizonyos kifejezések állhatnak a target helyén, úgy mint változók, mezők vagy
tömb elemek, ahova a sub el tudja tárolni a módosított értéket.
Ha ez az argumentum nincs megadva, akkor az alapérték a $0.
Például:
str = "water, water, everywhere" sub(/at/, "ith", str)az
str új értéke a "wither, water, everywhere" lesz,
mivel lecseréli az `at' legbaloldalibb, leghosszabb előfordulását
a `ith' szövegre.
A sub függvény az elvégzett behelyettesítések száma lesz (vagy egy
vagy zérus).
Ha a `&' speciális karakter előfordul a replacement-ben,
akkor ez a regexp-re illeszkedő szöveg részletet jelenti. (Ha regexp
egynél több szövegre illeszkedik, akkor ez a szöveg részlet változhat.)
Például:
awk '{ sub(/candidate/, "& and his wife"); print }'
a `candidate' első előfordulását lecseréli a `candidate
and his wife' szövegre a bemeneti file minden sorában.
Itt egy másik példa:
awk 'BEGIN {
str = "daabaaa"
sub(/a*/, "c&c", str)
print str
}'
-| dcaacbaaa
Ez azt mutatja be, hogy a `&' hogyan képes nem konstans szöveget
reprezentálni, és bemutatja, hogy mit jelent a "legbaloldalibb, leghosszabb"
szabály a reguláris kifejezések illesztésében
(see section Mennyi szöveg illeszkedik?).
A `&' speciális karakter hatása kikapcsolható, ha egy `\' karaktert
teszünk eléje. Mint mindig, ha egy szövegbe akarsz egy `\' karaktert
írni, akkor kettőt kell belőle leírni. Tehát a `\\&' karaktereket
kell egy szöveg konstansba beírni, hogy maga a `&' karakter
jelenjen meg a csere után. Például, itt bemutatjuk, hogy hogyan lehet az első
`|' karaktert lecserélni egy `&' karakterre minden sorban:
awk '{ sub(/\|/, "\\&"); print }'
Megjegyzés: Ahogy azt korábban írtuk a sub harmadik
argumentuma egy változó, egy mező vagy egy tömb eleme kell legyen. Az
awk néhány verziója megengedi, hogy a harmadik argumentum ne egy
lvalue legyen. Ebben az esetben a sub ugyanúgy viselkedik, de
a csere eredményét eldobja, mivel nincs hol tárolnia. Ezek az awk verziók
elfogadnák az alábbi kifejezést is:
sub(/USA/, "United States", "the USA and Canada")A történelmi kompatibilitás miatt a
gawk elfogadja a fenti hibás kódot is,
de bármilyen "nem megváltoztatható" objektum, mint harmadik argumentum esetén
fatális hibával leáll.
Végül, ha a regexp nem egy reguláris kifejezés, akkor egy szöveggé konvertálja
majd a szöveg értékét használja regexp-ként az illesztésben.
gsub(regexp, replacement [, target])
sub függvényhez, kivéve, hogy ez a függvény
minden legbaloldalibb, leghosszabb, nem átfedő, illeszkedő
szöveg részletet lecserél. A `g' a gsub névben a "globálist"
jelenti, vagyis cseréljen mindenhol. Például:
awk '{ gsub(/Britain/, "United Kingdom"); print }'
a `Britain' szöveg minden előfordulását lecseréli a `United
Kingdom' szövegre a bemeneti rekordokban.
A gsub függvény az elvégzett cserék számával tér vissza. Ha a harmadik
argumentum nincs megadva, akkor a keresést és a cserét a bemeneti rekordon,
$0, végzi el.
Ugyanúgy mint a sub-nál a `&' és `\' karakterek speciálisak,
és a harmadik argumentum egy lvalue kell legyen.
gensub(regexp, replacement, how [, target])
gensub egy általános helyettesítő függvény. Mint a sub és a
gsub a target szövegben a regexp kifejezésre illeszkedő szöveg
darabot keres. Ugyanakkor a sub és a gsub függvényekkel
ellentétben a módosított szöveg a függvény visszatérési értéke lesz, és az
eredeti target szöveg nem lesz módosítva. Ha a how egy
olyan szöveg ami a `g' vagy `G' karakterrel kezdődik,
akkor az összes illeszkedő szövegdarabot lecseréli a replacement
szövegre. Minden más esetben, a how egy szám kell legyen, ami
azt adja meg, hogy hanyadik illeszkedést kell lecserélni. Ha a target
nincs megadva, akkor a $0-t használja.
A gensub függvénynek van egy olyan szolgáltatása is, ami nem használható
sem a sub sem a gsub függvényekkel: a reguláris kifejezés
komponenseinek felhasználása a csereként szolgáló szövegben. Ezt úgy lehet
elérni, hogy zárójelek közé kell tenni a regexp adott komponensét és a
csereként szolgáló szövegben a `\n' kifejezést kell használni,
ahol az n egy egy és kilenc közé eső szám. Például:
$ gawk '
> BEGIN {
> a = "abc def"
> b = gensub(/(.+) (.+)/, "\\2 \\1", "g", a)
> print b
> }'
-| def abc
Ahogy azt a sub függvénynél elmagyaráztuk, két `\' karaktert kell
leírni ahhoz, hogy egy `\' karakter bekerüljön a szövegbe.
A csereként szolgáló szövegben a `\0' karakter sorozat a teljes
illeszkedő szöveget jelenti, ugyanúgy mint a `&' karakter.
Ez a példa bemutatja, hogy hogyan szabályozza a harmadik argumentum
azt, hogy melyik illeszkedés lesz lecserélve.
$ echo a b c a b c |
> gawk '{ print gensub(/a/, "AA", 2) }'
-| a b c AA b c
Ebben az esetben a $0 lesz a negyedik argumentum. A gensub
az új, csere utáni szöveggel tér vissza, amit átad a print-nek,
hogy nyomtassa ki.
Ha a how argumentum egy olyan szöveg, ami nem `g' vagy `G'
karakterekkel kezdődik, vagy egy zérusnál kisebb szám, akkor csak egy
helyettesítés hajtódik végre.
Ha a regexp nem illeszkedik a target egyik részére sem, akkor a
gensub visszatérési értéke az eredeti, változatlan target szöveg lesz.
A gensub egy gawk kiegészítés és "compatibility" módban
nem használható (see section Command Line Options).
substr(string, start [, length])
substr("washington", 5, 3) eredménye az "ing".
Ha a length nincs megadva, akkor a függvény a string szövegnek a
start karakterpozíciónál kezdődő és a szöveg végéig tartó részszövegével
tér vissza. Például, substr("washington", 5) eredménye az "ington".
Ugyanez történik ha a length nagyobb hosszat ad meg, mint ami a start
karakterpozíciótól a szöveg végéig tart.
Megjegyzés: A substr függvény által visszaadott
szövegnek nem lehet értéket adni. Így az alábbi kísérlet
a szöveg egy részének megváltoztatására hibás:
string = "abcdef" # ezt szeretnénk "abCDEf", de nem fog menni ! substr(string, 3, 3) = "CDE"A
substr függvényt nem lehet használni a sub vagy a gsub
függvények harmadik argumentumában sem:
gsub(/xyz/, "pdq", substr($0, 5, 20)) # HIBÁS
tolower(string)
tolower("MiXeD cAsE 123") eredménye a "mixed case 123".
toupper(string)
tolower("MiXeD cAsE 123") eredménye a "MIXED CASE 123".
sub, a gsub és a gensub függvényekben
Amikor a sub, a gsub vagy a gensub függvényen belül a
`\' vagy a `&' karaktert szeretnéd használni, akkor fontos arra
emlékezni, hogy az escape karakterek feldolgozásának több szintje van.
Először is van a lexikális szint, amikor is az awk
beolvassa a programodat és felépíti a programod belső reprezentációját, amit
majd végre tud hajtani.
Ezután van a futtatási szint, amikor az awk azt ellenőrzi a csereként
szolgáló szövegekben, hogy mit is kell csinálnia.
Mindkét szinten az awk ellenőrzi, hogy milyen karakter következik a
`\' karakter után. A lexikális szinten escape szekvenciákat keres
(section Escape szekvenciák). Így minden `\' karakterért, amit az awk
majd a futtatási szinten vesz figyelembe két `\' karaktert kell
megadni a lexikális szinten. Ha egy olyan karakter követi az `\'
karaktert, ami nem egy érvényes escape szekvencia, akkor a Unix awk
és a gawk is egyszerűen eltávolítja a `\' karaktert, és csak
a követő karaktert tartja meg a szövegben. Így például, a "a\qb"
szöveg a "aqb" szövegnek felel meg.
A futtatási szinten a különböző függvények különböző módon kezelik a `\' és a `&' karakterek használatát. A helyzet (sajnos) elég bonyolult.
Történelmileg a sub és a gsub függvények a `\&' karaktersorozatot
speciálisan kezelték; ezt a sorozatot a csereként használt szövegben
lecserélte a `&' karakterre. Minden más `\' karakter a
csereként szolgáló szövegen belül, amit nem a `&' karakter követett,
változatlan maradt. Ezt az alábbi táblázat illusztrálja:
Ez a táblázat bemutatja mind a lexikális feldolgozást, ahol a páratlan számú
`\' karakterek páros számúvá válnak a futtatási szinten,
és a sub által végrehajtott feldolgozást a futtatási szinten.
(Az egyszerűség kedvéért a későbbi táblázatokban csak a lexikális szinten
páros számú `\' karakterrel megadott eseteket mutatjuk be.)
A probléma a történelmi megközelítéssel az, hogy lehetetlen azt az esetet megadni, amikor az illeszkedő szöveget egy `\' karakter előzi meg.
Az 1992-es POSIX szabvány megpróbálta ezt a problémát megoldani. A szabvány
azt mondja ki, hogy a sub és a gsub függvények a `\' karakter
után vagy egy `\' vagy egy `&' karaktert keresnek. Ha bármelyik
eset előfordul, akkor a `\' karaktert követő karakter érintetlenül kerül
be a szövegbe. Tehát a `\' és a `&' karakterek értelmezése a következő:
Ez úgy tűnik megoldja a problémát. Sajnos, a szabvány szövege szokatlanul fogalmazza ezt meg. Azt mondja, hogy a `\' karakter kikapcsolja bármely követő karakter speciális jelentését, de a speciális jelentés kivéve a `\' és a `&' karaktereket nem definiált. Ez a fogalmazás két problémához vezet.
awk programok nem fognak helyesen működni.
awk program hordozható,
akkor a replacement szövegben minden karakter elé egy
`\' karaktert kell tenni.(12)
A POSIX szabvány átdolgozás alatt áll.(13)A fenti problémák miatt, az új, módosított változat olyan szabályokat ad meg, amelyek jobban hasonlítanak a régiekhez. Az új szabály speciális eseteket definiál arra az esetre, ha egy `\' karakternek kell megelőznie az illeszkedő szöveget.
Röviden, a futtatási szinten most három speciális eset van, a `\\\&', a `\\&' és a `\&'. Ezzel ellentétben régen csak egy volt. Ugyanakkor, mint a régi szabályban, bármely `\' karakter, ami nem része a három kivételnek nem speciális, és maga a karakter jelenik meg.
A gawk 3.0-ás verziója az új POSIX ajánlást követi a sub és a
gsub esetén.
Jelenleg még nem lehet tudni, hogy az új ajánlás végleg bekerül-e a szabványba.
A gawk jövőbeli verziói a szabványt fogják követni, bármi is legyen
a végleges szabványban; ekkor ezt a könyvet is frissíteni fogjuk.
A szabályok a gensub esetén sokkal egyszerűbbek. A futtatási szinten,
amikor a gawk egy `\' karaktert vesz észre, és a követő
karakter egy számjegy, akkor a reguláris kifejezésben elhelyezett
zárójelek a közötti illeszkedő szöveg fog megjelenni a kimenetben. Minden
más esetben, akármi is legyen a `\' karakter után, maga a karakter
fog megjelenni és a `\' karakter nem.
A lexikális és a futtatási szint bonyolultsága és a sub és a gsub
függvények speciális esetei miatt azt tanácsoljuk, hogy ha gawk-ot
használsz, akkor a gensub függvényt használd
helyettesítésre.
Az alábbi függvények a bemenettel vagy a kimenettel kapcsolatosak. Az opcionális argumentumok szögletes zárójelek ("[" and "]") között jelennek meg.
close(filename)
fflush([filename])
fflush függvény. A gawk is buffereli a
kimenetét, és az fflush függvénnyel lehet arra kényszeríteni, hogy
az adott pillanatban a buffer tartalmát kiírja.
Az fflush függvényt 1994-ben adták hozzá a Bell laboratóriumban
fejlesztett awk verzióhoz; a függvény nem része a POSIX szabványnak,
és nem használható ha a `--posix' opció szerepel a parancssorban
(see section Command Line Options).
A gawk kétféle módon fejlesztette tovább az fflush függvényt.
Az első, hogy argumentum nélkül is meg lehet hívni a függvényt. Ebben
az esetben a szabványos kimenet lesz ürítve. A második, hogy az üres
szöveg ("") is megadható argumentumként, amikor is
minden megnyitott file vagy cső buffere ürítve lesz.
Az fflush függvény zérus értékkel tér vissza ha sikeres volt
az ürítés, és egy nem zérus értékkel minden más esetben.
system(command)
system függvény teszi lehetővé, hogy a felhasználó bármilyen
az operációs rendszerben engedélyezett parancsot végrehajthasson, majd
az awk program futása folytatódjon. A system függvény
a command szövegben adott parancsot hajtja végre. A parancs
végrehajtása által visszaadott érték lesz a függvény visszatérési értéke.
Például, ha az alábbi programrészletet teszed be az awk programodba:
END {
system("date | mail -s 'awk run done' root")
}
akkor a rendszeradminisztrátor egy levelet fog kapni, amikor az
awk program befejezte a bemenete feldolgozását.
A print vagy a printf átirányítása egy csőbe gyakran elég
a feladat elvégzéséhez. Ha sok parancsot kell végrehajtani, akkor
hatékonyabb egy csőbe nyomtatni, ami egy shell-be van átirányítva:
while (amíg van mit csinálni)
print command | "/bin/sh"
close("/bin/sh")
Ugyanakkor ha az awk programod a felhasználótól is vár bemenetet
(interaktív), akkor a system függvény jól használható nagyobb
programok indítására, mint egy shell vagy egy szövegszerkesztő.
Néhány operációs rendszer nem támogatja a system függvény használatát,
ebben az esetben fatális hibát okoz a függvény hívása.
Érdemes itt megjegyezni, hogy a bufferelés zavarba ejtő is lehet ha a programod interaktív; pl. a program kommunikál a felhasználóval.(14)
Az interaktív programok általában soronként bufferelik a kimenetüket. A nem interaktív programok addig várnak amíg be nem tellik a bufferük, ami több sornyi kimenet is lehet, és csak ekkor írják ki a buffer tartalmát.
Itt egy példa a különbség bemutatására.
$ awk '{ print $1 + $2 }'
1 1
-| 2
2 3
-| 5
Control-d
Minden kimeneti sort azonnal kinyomtat. Hasonlítsd ezt össze a következő példával.
$ awk '{ print $1 + $2 }' | cat
1 1
2 3
Control-d
-| 2
-| 5
Itt addig nem ír ki semmit, amíg a Control-d billentyű kombinációt
meg nem kapja, mivel minden bufferelt, és egy menetben küld el mindent a
cat parancsnak a csövön keresztül.
system függvénnyel
Az fflush függvénnyel közvetlen szabályozható az egyes file-ok
vagy csövek bufferelése. Ugyanakkor sok más awk implementációban
ez a függvény nem támogatott. Egy alternatív megoldás a
bufferek kiürítésére, ha a
system függvényt hívjuk meg egy üres szöveg argumentummal:
system("") # kimenet ürítése
A gawk a system függvény ilyen használatát speciálisan kezeli,
és van annyira okos, hogy nem futtat egy shell-t (vagy más parancsértelmezőt)
egy üres paranccsal. Ezért a gawk esetén ez nem csak hasznos
megoldás, de hatékony is. Bár ez a megoldás más awk implementációkban
is működni fog, de nem biztos, hogy azok az awk implementációk
nem indítanak el egy shell-t. (Más implementációk lehet hogy csak a
szabványos kimenetet ürítik, és nem minden bufferelt kimenetet.)
Ha arra gondolsz, hogy egy programozó mit várna el, akkor egyértelmű, hogy a
system függvény üríti a még ki nem nyomtatott buffereket.
Az alábbi program:
BEGIN {
print "first print"
system("echo system echo")
print "second print"
}
ezt kell, hogy nyomtassa
first print system echo second print
és nem ezt
system echo first print second print
Ha az awk nem üríti a buffereit a system függvény hívása
előtt, akkor az utóbbi (nem kívánt) eredményt kapnánk.
Az awk programok egyik gyakori felhasználása a log file-ok
feldolgozása, amelyek dátum és idő információt is tartalmaznak. Sok
program a time rendszerfüggvény által megadott időt
használja a log file-okban. Ez az idő, a POSIX rendszereken,
az 1970 január 1-e (UTC), éjfél óta eltelt másodpercek száma.
Azért hogy ezeket a log file-okat egyszerűbb legyen feldolgozni,
a gawk két függvényt biztosít az időbélyegek kezelésére.
Mind a két függvény gawk kiterjesztés; sem a POSIX szabvány
nem tartalmazza, sem más awk implementációk.
Az opcionális paraméterek szögletes zárójelek ("[" and "]") között jelennek meg.
systime()
strftime([format [, timestamp]])
systime függvény
visszaadna. Ha nincs megadva a timestamp argumentum, akkor a
gawk az aktuális időt veszi alapul. Ha a format argumentum
nincs megadva, akkor az strftime függvény a
"%a %b %d %H:%M:%S %Z %Y" szöveget fogja használni.
Ez a formátum (majdnem) ugyanaz mint amit a date segédprogram
használ. (A gawk 3.0-ás verziója előtti verziókban a format
argumentumot mindig meg kellett adni.)
A systime függvény lehetővé teszi, hogy időbélyegeket hasonlíts
össze az aktuális időponttal. Például könnyű meghatározni, hogy mennyivel
korábban lett az adott log bejegyzés rögzítve.
Az strftime függvény lehetővé teszi, hogy ember számárá is olvasható
formában jelenjen meg az időbélyeg. Hasonló az sprintf függvényhez
(see section Szövegmanipuláló beépített függvények),
mivel minden nem formátum leíró karaktert ugyanúgy bemásol a szövegbe
és csak a formátum leírók helyeire teszi be az adott időpont, adott komponensét.
Az ANSI C szabvány által garantált, hogy az strftime függvény az alábbi
formátumleírókat támogatja:
%a
%A
%b
%B
%c
%d
%H
%I
%j
%m
%M
%p
%S
%U
%w
%W
%x
%X
%y
%Y
%Z
%%
Ha a formátum leíró nem a fentiek közül valamelyik, akkor a viselkedés nem definiált.(16)
Informálisan, a helyi azt a földrajzi helyet jelenti, ahol a programnak
futnia kell. Például az 1991 szeptember 4-ei dátum egy általános rövidítése
az Egyesült Államok területén a "9/4/91". Európa sok országában
a "4.9.91" rövidítést használnák. Így a `%x' a `9/4/91' szöveget
produkálja ha az "US" van definiálva, míg az "EUROPE"
esetén az eredmény a `4.9.91' lenne. Az ANSI C a "C"-t definiálja
mint helyi beállítás (locale), amit a legtöbb C programozó használ.
A gawk csomag a strftime függvény egy "public-domain"
C verzióját is tartalmazza olyan rendszerek számára, amelyek nem teljesen
ANSI kompatíbilisek. Ha a gawk ezzel a verzióval lett lefordítva
(see section Installing gawk), akkor az alábbi
formátumleírókat is lehet használni:
%D
%e
%h
%n
%r
%R
%T
%t
%k
%l
%C
%u
%V
%G
%g
%Ec %EC %Ex %Ey %EY %Od %Oe %OH %OI
%Om %OM %OS %Ou %OU %OV %Ow %OW %Oy
date segédprogrammal
kompatíbilis.)
%v
%z
Ez a példa a POSIX date segédprogram awk implementációja.
Általában a date az aktuális dátumot és időt nyomtatja ki egy
jól ismert formátumban. Ugyanakkor, ha olyan argumentumot
adsz meg ami `+' karakterrel kezdődik, akkor a date
a nem formátumleíró karaktereket közvetlenül kinyomtatja, míg az adott
formátumnak megfelelően írja ki az aktuális időt. Például:
$ date '+Today is %A, %B %d, %Y.' -| Today is Thursday, July 11, 1991.
Itt a gawk verziója a date segédprogramnak. Egy shell
"wrapper" veszi körbe, hogy a `-u' opciót is kezelje, ami
azt adja meg a date programnak, hogy UTC időzónában adja meg az időt.
#! /bin/sh
#
# date --- approximate the P1003.2 'date' command
case $1 in
-u) TZ=GMT0 # use UTC
export TZ
shift ;;
esac
gawk 'BEGIN {
format = "%a %b %d %H:%M:%S %Z %Y"
exitval = 0
if (ARGC > 2)
exitval = 1
else if (ARGC == 2) {
format = ARGV[1]
if (format ~ /^\+/)
format = substr(format, 2) # remove leading +
}
print strftime(format)
exit exitval
}' "$@"
Go to the first, previous, next, last section, table of contents.