Ocenite etot tekst:








          Proizvodstvenno-vnedrencheskij kooperativ

                    "I N T E R F E J S"













                Dialogovaya Edinaya Mobil'naya

                    Operacionnaya Sistema

                        Demos/P 2.1










        YAzyk obrabotki strukturirovannyh tekstov AWK
















                           Moskva

                            1988















Annotaciya

     YAzyk AWK  ispol'zuetsya  dlya  kombinirovannoj  obrabotki
simvol'nyh i chislovyh polej v zapisyah.  V rezul'tate generi-
ruetsya otchet v zaplanirovannoj programmistom  forme.   Prog-
rammy na yazyke AWK mozhno effektivno ispol'zovat' kak fil'try
dannyh dlya preobrazovaniya vyvoda odnoj programmy i  peredachi
rezul'tata fil'tracii na vhod drugoj.  V sisteme DEMOS usta-
novlen interpretator yazyka  AWK,  kotoryj  poluchil  nazvanie
awk.
























































1.  Principy raboty interpretatora awk


     Lyuboj tekst imeet  nekotoruyu  strukturu,  v  prostejshem
sluchae  ee  elementami  yavlyayutsya  stroki  i slova teksta.  V
yazyke AWK tekst rassmatrivaetsya kak spisok zapisej i polej v
nih  i  na  etoj  osnove  vypolnyaetsya nekotoryj opredelennyj
programmistom algoritm obrabotki. Dopustim, imeetsya  sleduyu-
shchij tekst:

Sidorov Sidor  Sidorovich      1957 g.r. 220 rub sl.
Petrov  Petr   Ivanovich       1962 g.r. 200 rub sl.
Ivanov  Mihail Konstantinovich 1965 g.r. 180 rub rab.
Volkov  Leonid Nikolaevich     1950 g.r. 280 rub rab.
Semenov Petr   Mihajlovich     1958 g.r. 210 rub rab.

|tot tekst strukturirovan: zapisi - eto stroki, polya v stro-
kah - slova i chisla.  V kazhdoj zapisi soderzhitsya po 8 polej,
razdelyayushchihsya probelami.  Znachashchim (v kachestve  razdelitelya)
yavlyaetsya  tol'ko odin probel mezhdu polyami, ostal'nye ignori-
ruyutsya.  Rassmotrim neskol'ko prostyh programm na yazyke AWK.

     Primer 1. AWK-programma  vyvodit  pervye  tri  polya  iz
vos'mi,  poryadok polej v vyvode izmenen i pered kazhdoj stro-
koj pechataetsya simvol tabulyacii

    { print( "\t", $2, $3, $1 ); }

Operator print vypolnyaetsya dlya vseh vhodnyh zapisej.   Posle
vypolneniya programmy poluchim:

    Sidor Sidorovich Sidorov
    Petr Ivanovich Petrov
    Mihail Konstantinovich Ivanov
    Leonid Nikolaevich Volkov
    Vladimir Mihajlovich Semenov

Kak vidno iz programmy, znacheniya polej podstavlyayutsya sleduyu-
shchim obrazom:

    $nomer_polya_v_zapisi

Pervomu polyu sootvetstvuet 1.  V obshchem sluchae  nomerom  polya
mozhet  byt'  znachenie  vyrazheniya.  Znacheniem  podstanovki $0
yavlyaetsya vsya zapis'.

     Primer 2.  AWK-programma  vyvodit  nomera  strok  posle
tabulyacii

    { print( "\t", NR, $2, $3, $1 ); }

Posle vypolneniya programmy poluchim:



                           - 3 -










    1 Sidor Sidorovich Sidorov
    2 Petr Ivanovich Petrov
    3 Mihail Konstantinovich Ivanov
    4 Leonid Nikolaevich Volkov
    5 Vladimir Mihajlovich Semenov

Predopredelennaya peremennaya NR ravna  nomeru  obrabatyvaemoj
zapisi.   My  vospol'zovalis'  ee  znacheniem  dlya  numeracii
strok.

     Primer 3. AWK-programma vyvodit  polnoe  chislo  let  na
1988 god kazhdomu licu iz spiska

{ print("\t", NR, $2, $3, $1, "\t\t", 1988 - $4); }

Posle vypolneniya programmy poluchim:

    1 Sidor Sidorovich Sidorov                31
    2 Petr Ivanovich Petrov                   26
    3 Mihail Konstantinovich Ivanov           23
    4 Leonid Nikolaevich Volkov               38
    5 Vladimir Mihajlovich Semenov            30


     Primer 4. AWK-programma podschityvaet srednij vozrast  i
srednyuyu zarabotnuyu platu perechislennyh v spiske lic

    {


    }

    END     {
        print ("Srednij  vozrast:\t",  age/NR );
        print ("Srednyaya zarplata:\t",  pay/NR );
    }

Posle vypolneniya programmy poluchim:

    Srednij  vozrast:        29.6
    Srednyaya zarplata:        218

Kogda neobhodimo obespechit' vyvod rezul'tata  po  zaversheniyu
spiska zapisej, ispol'zuetsya selektor END.  Peremennye age i
pay opredelyayutsya avtomaticheski kak chisla  v  moment  pervogo
ispol'zovaniya.  Vyrazheniya vychislyayutsya dlya vseh vhodnyh zapi-
sej.

     Primer 5. AWK-programma podschityvaet srednie vozrast  i
zarabotnuyu  platu rabochih i sluzhashchih v spiske. Dlya vydeleniya
strok so svedeniyami o rabochih ispol'zuetsya shablon  /rab/,  o
sluzhashchih - shablon /sl/.  SHablony soderzhat obrazcy dlya poiska
v polyah  zapisi.   Dannye  vyvodyatsya  posle  obrabotki  vseh


                           - 4 -










zapisej.

/rab/   {
    rage += 1988 - $4;
    rpay += $6;
    r++;
}

/sl/    {
    age += 1988 - $4;
    pay += $6;
    c++;
}

END     {
    print("\t\tSrednij vozrast  Srednyaya zarplata\n");
    print(" Rabochie:\t", rage/r, "\t",    rpay/r );
    print("Sluzhashchie:\t",  age/c, "\t\t",  pay/c );
}

Posle vypolneniya programmy poluchim:

             Srednij vozrast  Srednyaya zarplata

 Rabochie:        30.3333         223.333

Sluzhashchie:        28.5            210

Programma vypolnyaetsya  sleduyushchim  obrazom.   Esli  zapis'  v
kakom-libo  iz polej soderzhit obrazec, vypolnyaetsya dejstvie,
zapisannoe v figurnyh skobkah ryadom s sootvetstvuyushchim shablo-
nom,  inache  dejstvie  ne  vypolnyaetsya.  Dejstviya, ukazannye
posle END, vypolnyayutsya po koncu spiska zapisej.   SHablony  v
primere  ispol'zuyutsya  kak selektory vhodnyh zapisej: esli v
chetvertom primere dejstviya byli vypolneny dlya  vseh  vhodnyh
zapisej, to v etom - tol'ko dlya otobrannyh po obrazcam, uka-
zannym v shablonah. Pri etom END  ispol'zuetsya  kak  selektor
special'nogo  vida:  on  opredelyaet  spisok  operatorov AWK-
programmy, kotoryj dolzhen vypolnit'sya posle zaversheniya vhod-
nogo potoka zapisej.

     Primer 6.  AWK-programma  vychislyaet  urovni  zarabotnoj
platy












                           - 5 -










BEGIN  {
    Min = 1000;
    Max = 0;
}

{
    if ( $6 <&lt; Min ) {


    }

    if ( $6 >&gt; Max ) {


    }
}

END {
    print( "\t\tUrovni zarplaty\n" );
    print( " Minimal'nyj: ", Min, "  (",smin,")" );
    print( "Maksimal'nyj: ", Max, "  (",smax,")" );
}

Posle vypolneniya poluchim:

                Urovni zarplaty

 Minimal'nyj:  180   ( Ivanov Mihail Konstantinovich )

Maksimal'nyj:  280   ( Volkov Leonid Nikolaevich )

V etoj programme tri razdela. Pervyj razdel ispol'zuetsya dlya
ustanovki  nachal'nyh  znachenij  peremennyh  Max i Min eshche do
chteniya zapisej iz spiska.  Special'nyj selektor BEGIN  opre-
delyaet   spisok  operatorov  AWK-programmy,  kotoryj  dolzhen
vypolnit'sya do analiza pervoj zapisi iz vhodnogo potoka.  Vo
vtorom  razdele osushchestvlyaetsya sobstvenno obrabotka zapisej.
Operatory etogo razdela programmy vypolnyayutsya dlya vseh vhod-
nyh  zapisej,  tak  kak  selektor  ne ukazan.  Tretij razdel
vypolnyaetsya kogda zavershaetsya spisok zapisej (selektor END).
V stroke

    smin = $1 " " $2 " " $3;

peremennoj smin prisvaivayutsya  znacheniya  pervyh  treh  polej
zapisi,  konkatenaciya kotoryh vmeste s probelami, ukazannymi
v kavychkah, obrazuet stroku. Takim obrazom  znacheniem  pere-
mennoj   smin   budet  stroka  simvolov  tipa  "Familiya  Imya
Otchestvo".

     Sushchestvuet  neskol'ko  sposobov  vyzova  interpretatora
awk.  AWK-programma v fajle:



                           - 6 -










awk -f imya_fajla_s_AWK-programmoj  vhodnoj_fajl ...

Po umolchaniyu  razdelitelem  zapisej  yavlyaetsya  simvol  novoj
stroki, razdelitelem polej - simvol probela i/ili tabulyacii.
Simvoly-razdeliteli  mozhno  yavno  opredelit'  v   programme.
Simvol-razdelitel'  polej  mozhno  opredelit'  i  v komandnoj
stroke.  Vyzov awk s ukazaniem simvola-razdelitelya polej:

awk -Frazdelitel' -f fajl_AWK-programma  vhodnoj_fajl ...

CHasto AWK-programmy nastol'ko korotki, chto ih  celesoobrazno
ukazyvat'  neposredstvenno v komandnoj stroke, a ne v fajle.
Vyzov awk s programmoj v komandnoj stroke:

awk -Frazdelitel' 'AWK-programma'  vhodnoj_fajl ...

awk 'AWK-programma' vhodnoj_fajl ...

Interpretator awk, kak i bol'shinstvo  drugih  programm  sis-
temy, pozvolyaet vhodnoj_fajl zamenit' na standartnyj vvod.

awk -f imya_fajla_s_AWK-programmoj  -

awk -Frazdelitel' 'AWK-programma'  -

awk 'AWK-programma' -

Esli ne ukazano drugoe, rezul'tat  vypolneniya  AWK-programmy
pechataetsya na ekrane displeya.

2.  Peremennye, vyrazheniya i prisvaivaniya v AWK-programmah


     V yazyke AWK vydelyayut dve gruppy peremennyh: predoprede-
lennye  i  deklarirovannye  v  programme.   Predopredelennye
peremennye dostupny dlya podstanovok i izmenenij v programme,
ih  ishodnye  znacheniya ustanavlivayutsya interpretatorom awk v
processe zapuska i vypolneniya AWK-programmy.  K  predoprede-
lennym peremennym otnosyatsya:

NR   nomer tekushchej zapisi;

NF   chislo polej v tekushchej zapisi;

RS   razdelitel' zapisej na vvode (simvol);

FS   razdelitel' polej zapisi na vvode (simvol);

ORS  razdelitel' zapisej na vyvode AWK-programmy (simvol);

OFS  razdelitel' polej zapisi na vyvode (simvol);




                           - 7 -










OFMT format vyvoda chisel;

FILENAME imya vhodnogo fajla (stroka).


     Po umolchaniyu imeyut mesto sleduyushchie znacheniya predoprede-
lennyh peremennyh:

     RS    =   "\0";
     FS    =   'probel(y) i/ili tabulyaciya';
     OFS   =   FS;
     ORS   =   RS;
     OFMT  =   "%.6g";

Predopredelennym peremennym RS, FS,  ORS,  OFS,  OFMT  mozhno
prisvaivat' znacheniya v AWK-programme.

     V yazyke AWK otsutstvuyut deklaraciya i yavnaya  inicializa-
ciya  peremennoj lyubogo tipa. Vsyakoj peremennoj do ee pervogo
ispol'zovaniya prisvaivaetsya znachenie "\0" -  pustaya  stroka.
Primenyayutsya sleduyushchie tipy peremennyh:

pozicionnaya peremennaya;

chislo s plavayushchej tochkoj;

stroka simvolov;

massiv.

Pozicionnaya peremennaya opredelyaet  pole  zapisi,  soderzhimoe
kotorogo   mozhet   byt'   otneseno  k  tipam   "stroka"  ili
"chislo_s_tochkoj" i ispol'zuetsya v vide

    $nomer_polya_zapisi

    $(vyrazhenie)

Nomer_polya_zapisi mozhet byt' znacheniem vyrazheniya.  Znacheniem
pozicionnoj peremennoj $0 yavlyaetsya vsya zapis'.

     Interpretator awk rassmatrivaet peremennuyu kak  stroko-
vuyu  do  togo  momenta, kogda neobhodimo vypolnit' nekotoruyu
operaciyu nad ee znacheniem. V zavisimosti  ot  konteksta  tip
znacheniya peremennoj ostaetsya libo strokovym, libo preobrazu-
etsya k tipu chislo_s_tochkoj. V dvusmyslennyh  sluchayah   pere-
mennye  rassmatrivayutsya  kak  strokovye.  Stroki, kotorye ne
mogut byt' interpretirovany kak chisla, v chislovom  kontekste
budut  imet'  chislovoe znachenie NOLX.  Ustranit' dvusmyslen-
nost' mozhno yavnym ukazaniem tipa peremennoj pri prisvaivanii
ej znacheniya, naprimer:




                           - 8 -










name =  1 ;    # prisvoeno znachenie 1.0

name = "1";    # prisvoeno znachenie stroki "1"

Pri interpretacii vyrazhenij sushchestvennuyu  rol'  igraet  kon-
tekst, naprimer:

name =  3  +  2  ;

name =  3  + "2" ;

name = "3" + "2" ;

name =  3  +  2  +  "yabloko grusha apel'sin";

name = "yabloko" + "grusha";

V etom primere v pervyh chetyreh sluchayah name  ravno  5.0,  v
pyatom - 0.

     Massiv ne deklariruetsya,  on  nachinaet  sushchestvovat'  v
moment  pervogo ispol'zovaniya. Indeksy v massive mogut imet'
lyuboe nenulevoe znachenie,  vklyuchaya  nechislovye  stroki,  eto
pozvolyaet  ispol'zovat'  associativnye massivy. Naprimer,  v
privedennoj nizhe AWK-programme budet podschitano chislo upomi-
nanij ob avtomobilyah razlichnyh marok vo vhodnom tekste:

/ZIL/  { Avtomobili["ZIL"]++; }

/GAZ/  { Avtomobili["GAZ"]++; }

/VAZ/  { Avtomobili["VAZ"]++; }

END    {
    print("ZIL : ", Avtomobili["ZIL"]);
    print("GAZ : ", Avtomobili["GAZ"]);
    print("VAZ : ", Avtomobili["VAZ"]);
}

Massivy mozhno ispol'zovat' dlya organizacii takogo  algoritma
obrabotki  dannyh, v kotorom trebuetsya mnogokratnyj prosmotr
vhodnogo potoka zapisej.  Naprimer,  esli  ne  zabotit'sya  o
razmerah  operativnoj  pamyati,  to  mozhno  ves' vhodnoj fajl
zapisat' v vide massiva zapisej  i  po  zaversheniyu  vhodnogo
potoka pristupit' sobstvenno k obrabotke:










                           - 9 -










{
     Massiv_zapisej[NR] = $0
}

END  {
   ...
    programma obrabotki massiva
   ...
}

V kachestve imeni (znacheniya) indeksa massiva mozhno  ispol'zo-
vat' vyrazhenie, naprimer:

    name["2" * $3]


     V yazyke AWK ispol'zuyutsya operatory prisvaivaniya

    =   +=   -=   *=   /=   %=

i arifmeticheskie operacii

    +    -    *    /    %    ++    --

Oni imeyut tot zhe smysl, chto i v yazyke programmirovaniya Si.

     Imeyutsya nekotorye osobennosti vypolneniya operacij srav-
neniya

    <&lt;    <&lt;=    ==    !=     >&gt;=     >&gt;

Esli oba operanda interpretiruyutsya kak chisla, to vypolnyaetsya
sravnenie  chisel.   Esli  odin iz operandov yavlyaetsya strokoj
simvolov, a drugoj - chislom, to vypolnyaetsya sravnenie strok.
Sravnenie  strok zaklyuchaetsya v poparnom sravnenii vnutrennih
kodov simvolov strok do pervogo  neravenstva  kodov  ili  do
zaversheniya odnoj iz strok. Rassmotrim primer:

{
 if( $1 <&lt;   $2 )
   print(NR": $1 =", $1, "; $2 =", $2, "; $1 <  $2");

 if( $1 ==  $2 )
   print(NR": $1 =", $1, "; $2 =", $2, "; $1 == $2");

 if( $1 >&gt;   $2 )
   print(NR": $1 =", $1, "; $2 =", $2, "; $1 >  $2");
}

Dopustim, imeetsya sleduyushchij vhodnoj tekst:





                           - 10 -










    2.01    2.02
    2.01    abc
    a       b
    aa      b
    aa      ab
    aa      ba
    abc     ab
    ab      abc
    ef      abc

V rezul'tate vypolneniya programmy poluchim:

    1: $1 = 2.01; $2 = 2.02; $1 <  $2
    2: $1 = 2.01; $2 = abc ; $1 <  $2
    3: $1 = a   ; $2 = b   ; $1 <  $2
    4: $1 = aa  ; $2 = b   ; $1 <  $2
    5: $1 = aa  ; $2 = ab  ; $1 <  $2
    6: $1 = aa  ; $2 = ba  ; $1 <  $2
    7: $1 = abc ; $2 = ab  ; $1 >  $2
    8: $1 = ab  ; $2 = abc ; $1 == $2
    9: $1 = ef  ; $2 = abc ; $1 >  $2


     V AWK-programmah mozhno ispol'zovat' sleduyushchie  logiches-
kie operacii:

    ! (ne)     || (ili)     &&  (i)

Kak obychno, znacheniem vyrazheniya, soderzhashchego operacii  otno-
sheniya  i/ili logicheskie operacii, yavlyayutsya: istina (ne nol')
ili lozh' (nol').  Prioritety operacij  v  vyrazheniyah  analo-
gichny  ustanovlennym  v  yazyke  Si.  Dlya upravleniya poryadkom
vypolneniya operacij v vyrazhenii ispol'zuyutsya kruglye skobki.

     V yazyke AWK imeetsya operaciya, ne predusmotrennaya v  Si,
- eto operaciya "probel", kotoraya ispol'zuetsya dlya konkatena-
cii peremennyh, znacheniya kotoryh interpretiruyutsya kak  stro-
kovye

    name = "yabloko " "i grusha";

V etom sluchae znacheniem peremennoj name budet stroka vida

    "yabloko i grusha"

Vmesto simvola probel mozhno ispol'zovat'  simvol  tabulyacii.
Pri  ispol'zovanii  operacii  "probel" uchityvaetsya kontekst,
naprimer:







                           - 11 -










$1 = "yabloko"

$2 = "i"

$3 = "grusha"

name1 = $3 $2 $1;              #  1
name2 = $3" "$2" "$1;          #  2
name3 = "Krasnoe " $1;         #  3
name4 = 1 2 3 4 5 6 7 8 9;     #  4
name5 = 123           789;     #  5
name6 = $3$2$1;                #  6
name7 = $3 123;                #  7

znacheniem peremennoj name1 budet stroka:

    "grushaiyabloko"

Znacheniem peremennoj name2 budet stroka:

    "grusha i yabloko"

Znacheniem peremennoj name3 budet stroka:

    "Krasnoe yabloko"

Znacheniem peremennoj name4 budet stroka:

    "123456789"

Znacheniem peremennoj name7 budet stroka:

    "grusha123"

Znacheniem peremennoj name5 budet stroka:

    "123789"

Iz primera 5 vidno, chto v kachestve znaka  operacii  "probel"
sushchestvenno  nalichie  lish'  odnogo probela mezhdu operandami,
ostal'nye ignoriruyutsya.  Znacheniem  peremennoj  name6  budet
stroka vida

    "grushaiyabloko"

Odnako sintaksis, ispol'zovannyj v 6 stroke primera,  somni-
telen  i  ne  stoit  polagat'sya na "mudrost'" interpretatora
awk.

     Pozicionnye peremennye mozhno ispol'zovat' v  vyrazheniyah
lyubogo vida, im mozhno prisvaivat' novye znacheniya. Rassmotrim
neskol'ko primerov:



                           - 12 -










$3  =  $1 " " $2;
$3 +=  $1;
$3  =  $3 $3 $3;
$3  =  "";
$0  =  $3;

V pervom  sluchae  pozicionnoj  peremennoj  $3  prisvaivaetsya
stroka,  poluchennaya v rezul'tate konkatenacii znacheniya pozi-
cionnoj peremennoj $1, probela i znacheniya pozicionnoj  pere-
mennoj $2.  Vo vtorom sluchae znachenie peremennoj $3 uvelichi-
vaetsya na znachenie peremennoj $1.  V tret'em sluchae vypolnya-
etsya  konkatenaciya  sobstvennogo  znacheniya  peremennoj $3, v
chetvertom - peremennoj  $3  prisvaivaetsya  znacheniie  pustoj
stroki,  v pyatom - znachenie peremennoj $0 (vsya zapis') zame-
nyaetsya znacheniem polya 3.

3.  Struktura AWK-programmy


     AWK-programma sostoit iz spiska pravil vida:

selektor1     {  dejstvie  }
      ...
selektorN     {  dejstvie  }

Otkryvayushchaya figurnaya skobka dolzhna stoyat' v toj  zhe  stroke,
gde selektor. V lyubom meste programmy mozhno vvesti kommenta-
rij, on pechataetsya ot simvola # do konca stroki.

     Kazhdoe pravilo vypolnyaetsya dlya kazhdoj zapisi  iz  vhod-
nogo  potoka. Selektor ispol'zuetsya dlya togo, chtoby vydelit'
zapis', nad kotoroj budet vypolneno  dejstvie  sootvetstvuyu-
shchego  pravila.  Esli zapis' ne vydelena ni odnim iz selekto-
rov, ona ignoriruetsya i ne vyvoditsya na  standartnyj  vyvod.
Esli  zapis' vydelena selektorom, vypolnyaetsya dejstvie soot-
vetsvuyushchego pravila. Esli  nekotoruyu  zapis'  vydelyayut  nes-
kol'ko selektorov, nad nej vypolnyayutsya dejstviya sootvetstvu-
yushchih pravil.

     V pravile mozhet otsutstvovat' selektor, togda  dejstvie
etogo  pravila budet vypolneno dlya vseh bez isklyucheniya vhod-
nyh zapisej.  V pravile mozhet otsutstvovat' dejstvie,  togda
vse  vydelennye  selektorom zapisi budut napravleny na stan-
dartnyj vyvod bez izmenenij.

     Opredeleny dva pravila special'nogo vida:









                           - 13 -










BEGIN         {  dejstvie  }

      ...
spisok drugih pravil
      ...

END           {  dejstvie  }

Pravilo s selektorom  BEGIN  vypolnyaetsya  do  chteniya  pervoj
vhodnoj  zapisi,  s  selektorom END - posle chteniya poslednej
zapisi.  Pravilo s selektorom BEGIN  dolzhno  byt'  pervym  v
spiske pravil, s selektorom END - poslednim.  Vozmozhno takoe
ispol'zovanie etih pravil:

BEGIN         {  dejstvie  }

      ...
spisok drugih pravil

ili

spisok drugih pravil
      ...

END           {  dejstvie  }

Dejstvie v  pravile  mozhet  soderzhat'  spisok  operatorov  i
upravlyayushchih  konstrukcij. Operator dolzhen zakanchivat'sya sim-
volom ";", ili simvolom novoj stroki, ili zakryvayushchej  skob-
koj.

     Peremennuyu mozhno  ispol'zovat'  v  lyubom  pravile  AWK-
programmy,  nachinaya  s mesta, gde ona opredelena. Rassmotrim
primer, v  kotorom  demonstriruyutsya  osobennosti  vypolneniya
pravil AWK-programmy i ispol'zovaniya peremennyh:




















                           - 14 -










    # Programma   demonstriruet    rabotu
    # pravil  razlichnogo  vida  i oblast'
    # dejstviya peremennyh

    # Pravilo 1 vypolnyaetsya
    # dlya vseh zapisej

         { print("Zapis' nomer:", NR); }

    # Pravilo  2  vypolnyaetsya  tol'ko dlya
    # zapisej, gde obnaruzhen obrazec aaa

    /aaa/ {
       print("Pravilo 2:");
       print("     Vhod:", $0);
       $1 = $1  $2;
       $2 = "***";
       A  = $2;
       print("Rezul'tat:", $0, "A =", A);
    }

    # Pravilo  3  vypolnyaetsya  tol'ko dlya
    # zapisej, gde obnaruzhen obrazec ddd

    /ddd/ {
       print("Pravilo 3:");
       print("     Vhod:", $0);
       $1 = $1 $3;
       $2 =  "&&&";
       A  = $2;
       print("Rezul'tat:", $0, "A =", A);
    }

    # Pravilo 4 vypolnyaetsya dlya vseh zapisej

    {
       print("Pravilo 4:", $0, "A =", A,"\n");
    }

Dopustim, na vhod etoj programme  peredayutsya  sleduyushchie  tri
zapisi:

    eee fff
    ddd eee fff
    aaa bbb ccc ddd eee

togda posle vypolneniya programmy poluchim:








                           - 15 -










    Zapis' nomer: 1
    Pravilo 4: eee fff A =

    Zapis' nomer: 2
    Pravilo 3:
         Vhod: ddd eee fff
    Rezul'tat: dddfff &&& fff A = &&&
    Pravilo 4: dddfff &&& fff A = &&&

    Zapis' nomer: 3
    Pravilo 2:
         Vhod: aaa bbb ccc ddd eee
    Rezul'tat: aaabbb *** ccc ddd eee A = ***
    Pravilo 3:
         Vhod: aaabbb *** ccc ddd eee
    Rezul'tat: aaabbbccc &&& ccc ddd eee A = &&&
    Pravilo 4: aaabbbccc &&& ccc ddd eee A = &&&


4.  Selektory


     Selektor ukazyvaetsya, chtoby opredelit', budet li vypol-
nyat'sya  dejstvie  v pravile. V kachestve selektora mozhet byt'
ispol'zovano lyuboe vyrazhenie, shablon i proizvol'naya ih  kom-
binaciya. Rassmotrim neskol'ko primerov ispol'zovaniya vyrazhe-
nij v selektorah:

$1 != $2 || $1 >&gt; 128
     vybrat' zapis', v kotoroj libo  pervye  dva  polya  raz-
     lichny, libo soderzhimoe pervogo polya bol'she 128;

$1 % $2 == 1
     vybrat' zapis', v  kotoroj  ostatok  ot  deleniya  polej
     raven 1;

NF % 2 == 0 || name <&lt; 2.2
     vybrat' zapis', libo  soderzhashchuyu  chetnoe  chislo  polej,
     libo esli peremennaya name men'she 2.2;

     $1 == "Ivanov I.I."

     vybrat' zapis', v kotoroj pervoe pole otnositsya k  Iva-
novu I.I.;

$1 >&gt;= "M" && $1 != "Moskva"

     vybrat' zapis', pervoe pole kotoroj nachinaetsya s  bukvy
M i dalee po alfavitu, no ne yavlyaetsya slovom Moskva.

     SHablon ispol'zuetsya dlya formirovaniya odnogo  ili  bol'-
shego  chisla  obrazcov  v selektore. Pri skanirovanii vhodnoj
zapisi osushchestvlyaetsya poisk cepochki simvolov,  tozhdestvennoj


                           - 16 -










obrazcu.   V  prostejshem sluchae selektor s shablonom vyglyadit
sleduyushchim obrazom:

    /obrazec/

V simvolah / ukazan obrazec, kotoryj budet  ispol'zovan  dlya
poiska.   Sushchestvenno, chto lyuboj simvol, v tom chisle probel,
ukazannyj vnutri pary simvolov /, yavlyaetsya chast'yu obrazca.

     Esli neobhodimo, chtoby sootvetstvie  obrazcu  opredelya-
los'  v konkretnom pole zapisi, ispol'zuyutsya operatory soot-
vetstviya (~ i !~)

$nomer_polya ~  shablon
     esli  pri  prosmotre  ukazannoj  pozicionnoj  permennoj
     obnaruzhivaetsya  cepochka simvolov, tozhdestvennaya obrazcu
     v shablone (operator ~), vypolnyaetsya dejstvie pravila.

$nomer_polya !~ shablon
     esli pri prosmotre ukazannoj pozicionnoj  permennoj  ne
     obnaruzhivaetsya  cepochka simvolov, tozhdestvennaya obrazcu
     v shablone (operator !~), vypolnyaetsya dejstvie pravila.


     V  obshchem  sluchae  shablon  mozhet  formirovat'  mnozhestvo
obrazcov  i/ili  ukazyvat',  v kakom meste zapisi neobhodimo
iskat' sootvetstvie vhodnoj cepochki simvolov  obrazcu.   Pri
neobhodimosti ispol'zuyutsya tak nazyvaemye regulyarnye vyrazhe-
niya, v etom sluchae shablon vyglyadit sleduyushchim obrazom:

    /regulyarnoe_vyrazhenie/

V rezul'tate razbora regulyarnogo  vyrazheniya  interpretatorom
awk  stroitsya i vypolnyaetsya algoritm poiska odnogo ili bol'-
shego chisla obrazcov vo vhodnoj zapisi.

     Regulyarnye vyrazheniya v shablonah selektorov  AWK  analo-
gichny  podobnym v lex, redaktore ed i v komande grep.  Regu-
lyarnoe vyrazhenie formiruetsya kak kompoziciya cepochek simvolov
(i/ili  diapozonov simvolov) i operatorov. Operatory v regu-
lyarnyh vyrazheniyah ukazyvayutsya  v  vide  simvolov-operatorov.
CHtoby  otnesti dejstvie simvola-operatora k otdel'nomu frag-
mentu regulyarnogo vyrazheniya,  ispol'zuyutsya  kruglye  skobki.
CHtoby  otmenit'  special'noe znachenie simvola-operatora, ego
ekraniruyut simvolom \.

     Dlya zapisi regulyarnyh vyrazhenij upotreblyayutsya sleduyushchie
simvoly-operatory:

^    ot nachala;

$    na konce;



                           - 17 -










.    lyuboj simvol;

simvol
     dannyj simvol, esli on ne simvol-operator;

\simvol
     ispol'zovat' simvol-operator kak obychnyj simvol;

[stroka]
     lyuboj iz simvolov dannoj stroki;

[bukva1-bukva2]
     lyubaya bukva iz dannogo leksikograficheski uporyadochennogo
     diapazona bukv;

[cifra1-cifra2]
     lyubaya cifra iz dannogo diapazona cifr;

reg_vyrazhenie*
     0 ili bolee vhozhdenij regulyarnogo vyrazheniya;

reg_vyrazhenie+
     1 ili bolee vhozhdenij regulyarnogo vyrazheniya;

reg_vyrazhenie?
     0 ili 1 vhozhdenie regulyarnogo vyrazheniya;

reg_vyrazhenie1 reg_vyrazhenie2
     posledovatel'noe     vhozhdenie     reg_vyrazhenie1     i
     reg_vyrazhenie2;

reg_vyrazhenie1|reg_vyrazhenie2
     vhozhdenie reg_vyrazhenie1 ili reg_vyrazhenie2;


     Rassmotrim neskol'ko primerov ispol'zovaniya  regulyarnyh
vyrazhenij:

/^Ivanov/
     vydelit' zapis', nachinayushchuyusya cepochkoj  simvolov  "Iva-
     nov"  Takim  obrazom,  budut vydeleny sluchai tipa "Iva-
     novu", "Ivanovoj", ... ;

$3 ~ /^Ivanov/
     vydelit'  zapis',  v  kotoroj  tret'e  pole  nachinaetsya
     cepochkoj simvolov "Ivanov";

/([abc][ABC])$/
     vydelit' zapis', predposlednim simvolom  kotoroj  yavlya-
     etsya odna iz bukv abc i poslednim - odna iz bukv ABC;

/[0-9]+/
     vydelit' zapis', soderzhashchuyu ne menee odnoj cifry;


                           - 18 -










$3 !~ /(Sidor)|(Petr)/
     ne vydelyat' zapis', soderzhashchuyu v tret'em pole  chto-libo
     o Sidorah ili Petrah;


     Nizhe priveden primer  AWK-programmy,  pechatayushchej  imena
registracionnyh  katalogov  i  imena vseh pol'zovatelej sis-
temy, kotorymi ne ustanovlen parol':

    BEGIN  {
            FS = ":";
            print("Imya\tKatalog");
    }

    $2 !~ /(([0-9])|([a-z])|([A-Z]))+/  {
            print( $1, "\t", $6);
    }

V pervom pravile (selektor BEGIN) menyaetsya razdelitel' polej
zapisi  s  probela  na dvoetochie (takova struktura zapisej v
parol'nom fajle /etc/passwd operacionnoj sistemy DEMOS).  Vo
vtorom pole zapisi parol'nogo fajla soderzhitsya zashifrovannyj
parol' - obychno eto kombinaciya cifr i bukv.  Esli parol'  ne
ustanovlen, to vtoroe pole zapisi pusto. |tot fakt ispol'zo-
van dlya formirovaniya  selektora  -  vtoroe  pole  ne  dolzhno
soderzhat'  cifr i bukv. Selektor vydelyaet vtoroe pole zapisi
i proveryaet nalichie ne menee odnogo  simvola  v  etom  pole.
Esli pole pusto, vypolnyaetsya dejstvie, kotoroe zaklyuchaetsya v
pechati imeni pol'zovateya (pervoe pole) i imeni registracion-
nogo kataloga pol'zovatelya (shestoe pole).

     Inogda  neobhodimo  opredelit'  diapazon  zapisej,  dlya
kotoryh  vypolnyaetsya  dejstvie. Naprimer, neobhodimo vyvesti
na pechat' zapisi s nomerami ot 10 do 20  vklyuchitel'no.  Ili,
dopustim,  vyvesti  na  pechat'  pole  nomer 6 kazhdoj zapisi,
nachinaya s toj, v kotoroj vtoroe pole "Petr", do toj, v koto-
roj  pyatoe pole "Sidor". Dlya opredeleniya diapazona zapisej v
selektorah ispol'zuetsya operaciya zapyataya. Do zapyatoj  ukazy-
vaetsya selektor, vydelyayushchij pervuyu zapis' v diapazone, posle
zapyatoj - selektor, vydelyayushchij poslednyuyu zapis' v diapazone.
Takim  obrazom,  my  imeem delo s sostavnym selektorom.  Dlya
vseh zapisej diapazona vypolnyaetsya dejstvie pravila  s  sos-
tavnym selektorom.

     Rassmotrim primer. Dopustim, imeetsya sleduyushchij fajl:










                           - 19 -










    sss   pole2 pole3 pole4  1
    pole1 sss   pole3 pole4  2
    pole1 pole2 sss   pole4  3
    pole1 pole2 pole3 sss    4
    ttt   pole2 pole3 pole4  5
    pole1 ttt   pole3 pole4  6
    pole1 pole2 ttt   pole4  7
    pole1 pole2 pole3 ttt    8

Dopustim, neobhodimo vyvesti  na  pechat'  diapazon  zapisej.
Otkryvaet etot diapazon zapis', vtoroe pole kotoroj "sss", i
zakryvaet zapis', tret'e pole kotoroj "ttt". Togda programma
vyglyadit sleduyushchim obrazom:

    $2 ~ /sss/, $3 ~ /ttt/   {
            print( $0 );
    }

V rezul'tate vypolneniya poluchim:

    pole1 sss   pole3 pole4  2
    pole1 pole2 sss   pole4  3
    pole1 pole2 pole3 sss    4
    ttt   pole2 pole3 pole4  5
    pole1 ttt   pole3 pole4  6
    pole1 pole2 ttt   pole4  7


     V odnoj programme mozhno ukazat' neskol'ko pravil s sos-
tavnymi  selektorami.  Pri  etom  esli  vydelennye diapazony
perekryvayutsya, to kazhdaya vydelennaya zapis'  budet  obrabaty-
vat'sya  neskol'kimi  pravilami. Naprimer, dlya togo zhe ishod-
nogo fajla ispol'zuetsya sleduyushchaya programma obrabotki:

    $2 ~ /sss/, $3 ~ /ttt/   {
            print( $0 );
    }

    $1 ~ /sss/, NR == 5    {
            print($0, "*");
    }

    NR == 6, NR == 8       {
            print( $0, "<-" );
    }

V rezul'tate vypolneniya poluchim:








                           - 20 -










    sss   pole2 pole3 pole4  1 *
    pole1 sss   pole3 pole4  2
    pole1 sss   pole3 pole4  2 *
    pole1 pole2 sss   pole4  3
    pole1 pole2 sss   pole4  3 *
    pole1 pole2 pole3 sss    4
    pole1 pole2 pole3 sss    4 *
    ttt   pole2 pole3 pole4  5
    ttt   pole2 pole3 pole4  5 *
    pole1 ttt   pole3 pole4  6
    pole1 ttt   pole3 pole4  6 <-
    pole1 pole2 ttt   pole4  7
    pole1 pole2 ttt   pole4  7 <-
    pole1 pole2 pole3 ttt    8 <-


     CHtoby ustranit' effekt peresecheniya diapazonov  vydelen-
nyh  zapisej,  tam,  gde  eto neobhodimo, mozhno ispol'zovat'
operator next. |tot operator  prekrashchaet  obrabotku  tekushchej
zapisi,  upravlenie peredaetsya na nachalo programmy i nachina-
etsya razbor sleduyushchej zapisi. Teper' programma  budet  imet'
vid:

    $2 ~ /sss/, $3 ~ /ttt/   {
            print( $0 );
            next;
    }

    $1 ~ /sss/, NR == 5    {
            print($0, "*");
            next;
    }

    NR == 6, NR == 8       {
            print( $0, "<-" );
    }

V rezul'tate vypolneniya programmy poluchim:

    sss   pole2 pole3 pole4  1 *
    pole1 sss   pole3 pole4  2
    pole1 pole2 sss   pole4  3
    pole1 pole2 pole3 sss    4
    ttt   pole2 pole3 pole4  5
    pole1 ttt   pole3 pole4  6
    pole1 pole2 ttt   pole4  7
    pole1 pole2 pole3 ttt    8 *

Iz primera vidno, chto v ishodnom spiske ne nashlos' ni  odnoj
zapisi,  kotoraya byla by obrabotana vsemi pravilami i dejst-
vie tret'ego pravila programmy ne vypolnyalos' voobshche.




                           - 21 -










     Esli v rezul'tate vypolneniya pravila s sostavnym selek-
torom  vydeleno  nachalo diapazona zapisej, no ne vydelen ego
konec, dejstvie etogo pravila vypolnyaetsya dlya  vseh  zapisej
do  konca  vvoda.  Esli zhe ne obnaruzhena zapis', otkryvayushchaya
diapazon zapisej, to dejstvie pravila s sostavnym selektorom
ne vypolnyaetsya.

5.  Dejstviya


     Dejstviya v pravilah AWK-programmy  opredelyayut  algoritm
obrabotki  vydelennyh  selektorom  zapisej. Dlya zapisi algo-
ritma ispol'zuyutsya prisvaivaniya, vyrazheniya, operatory uprav-
leniya, operatory vyvoda, vstroennye funkcii.

     Vyshe bylo pokazano, chto dejstvie v pravile zapisyvaetsya
kak  blok  (v  smysle  yazyka  programmirovaniya Si). Figurnaya
skobka,  otkryvayushchaya  blok,  dolzhna  ukazyvat'sya  v  toj  zhe
stroke, chto i selektor, zakryvayushchaya - po zaversheniyu bloka. V
obshchem sluchae blok mozhet byt' pustym,  togda,  kak  eto  bylo
skazano  vyshe, vse zapisi, vydelennye selektorom, peredayutsya
na standartnyj vyvod bez preobrazovanij.

     K chislu operatorov upravleniya otnosyatsya:

exit
     zavershit' vypolnenie programmy;

next
     perejti k chteniyu sleduyushchej zapisi.  Upravlenie  pereda-
     etsya na pervoe pravilo AWK-programmy (esli imeetsya pra-
     vilo s selektorom BEGIN, to na sleduyushchee za nim);

break
     preryvaet vypolnenie  ohvatyvayushchego  cikla.  Upravlenie
     peredaetsya na operator, sleduyushchij za ciklom;

continue
     perehod k sleduyushchej iteracii cikla;

if(vyrazhenie) { blok_1 }  else { blok_2 }
     esli znachenie vyrazheniya - istina, vypolnyayutsya operatory
     bloka_1,  inache  operatory  bloka_2.  CHast'  else mozhno
     opustit'. Esli blok_1 ili  blok_2  soderzhat  po  odnomu
     operatoru, figurnye skobki mozhno ne ukazyvat';

while(vyrazhenie) { blok }
     operatory bloka vypolnyayutsya, poka znachenie vyrazheniya  -
     istina.   Esli  v bloke tol'ko odin operator,  figurnye
     skobki mozhno ne ukazyvat';

for(vyrazhenie_1; vyrazhenie_2; vyrazhenie_3) { blok }
     esli  znachenie  vyrazheniya_2   -   istina,   vypolnyayutsya


                           - 22 -










     operatory  bloka.  Vyrazhenie_1 vychislyaetsya pered pervoj
     iteraciej cikla, vyrazhenie_3 vychislyaetsya na kazhdoj ite-
     racii cikla. Esli blok soderzhit odin operator, figurnye
     skobki mozhno ne ukazyvat'.

for( indeks in imya_massiva ) { blok }
     dlya kazhdogo znacheniya indeksa massiva vypolnyayutsya opera-
     tory bloka.  Znachenie indeksa formiruetsya avtomaticheski
     na kazhdoj iteracii  cikla  i  ravno  znacheniyu,  eshche  ne
     ispol'zovannomu  v cikle. Esli ispol'zuetsya associativ-
     nyj massiv,  indeks  formiruetsya  v  leksikograficheskom
     poryadke.  Esli  v bloke proishodit dobavlenie elementov
     massiva, rezul'tat vypolneniya cikla nepredskazuem. Esli
     v bloke izmenyaetsya znachenie indeksa, rezul'tat vypolne-
     niya cikla nepredskazuem.  Vmesto  indeksa  i/ili  imeni
     massiva  mozhno  ukazat'  vyrazhenie,  znachenie  kotorogo
     interpretiruetsya kak indeks i/ili imya massiva.


     V kachestve uslovnyh vyrazhenij mozhno ispol'zovat'  lyubye
iz  opisannyh  vyshe.  V  vyrazheniyah mozhno primenyat' shablony,
operatory ~ i !~. Rassmotrim primer:

    /aaa/ {
            if( $3 !~ /fff/ )
                    print( $0 );
    }

V zapisi, vydelennoj po selektoru /aaa/,  proveryaetsya  soot-
vetstvie  soderzhimogo polya $3 shablonu /fff/.  Esli sootvets-
vie ne obnaruzheno,  pechataesya  vsya  zapis',  inache  operator
print ne vypolnyaetsya.

     Teper' rassmotrim primer  ispol'zovaniya  cikla  for  po
ideksu  v  associativnom  massive.  Dopustim, imeetsya spisok
zapisej

    aaa aaa ddd ccc
    ccc ddd
    bbb ddd ddd
    ccc

i pust' vypolnyaetsya programma












                           - 23 -










    /bbb/   { m["bbb"]++; }

    /ccc/   { m["ccc"]++; }

    /aaa/   { m["aaa"]++; }

    /ddd/   { m["ddd"]++; }

    END     { for( i in m )
                     print("m["i"] =", m[i]);
    }

V kazhdom iz pervyh  chetyreh  pravil  selektorami  vydelyayutsya
zapisi  i podschityvaetsya chislo takih zapisej v associativnom
massive s imenem m.   Cikl  for  vypolnyaetsya  po  zaversheniyu
spiska  vhodnyh  zapisej.  V rezul'tate vypolneniya programmy
poluchim:

    m[aaa] = 1
    m[bbb] = 1
    m[ccc] = 3
    m[ddd] = 3

Znacheniem kazhdogo elementa massiva yavlyaetsya chislo vydelennyh
selektorami   zapisej.  V  rezul'tate  vypolneniya  cikla  po
indeksu v associativnom massive poluchen vyvod znachenij  ele-
mentov   massiva   v   leksikograficheskom  poryadke  znachenij
indeksa.

     Nizhe priveden primer programmy, dejstviya kotoroj soder-
zhat primery ispol'zovaniya osnovnyh  upravlyayushchih konstrukcij.
Dopustim, imeetsya sleduyushchij tekst:

    aaa, aaa, aaa  aaa  aaa.
    aaa  aaa, aaa, aaa  aaa.
    aaa  aaa  aaa, aaa  aaa.
    aaa  aaa  aaa  aaa, aaa.
    aaa; aaa  aaa  aaa: aaa.
    aaa  aaa; aaa  aaa  aaa.
    aaa  aaa  aaa; aaa; aaa.
    aaa  aaa: aaa  aaa; aaa.
    aaa: aaa  aaa; aaa  aaa.
    aaa  aaa  aaa: aaa: aaa.

Trebuetsya poluchit' nekotoruyu statistku o tekste:










                           - 24 -










# Programma vychislyaet statisticheskie
# harakteristiki teksta.
# Razdelitel' zapisej tochka.
# Razdelitel' polej probel.
# Vyvod rezul'tatov osushchestvlyaetsya
# posle zaversheniya vhodnogo teksta.

BEGIN {
      # vydelenie i inicializaciya
      # peremennyh

      RS = "."; # razdelitel' zapisej
      Nw = 0;   # chislo slov
      Nb = 0;   # chislo simvolov v slovah
      Np = 0;   # chislo zapyatyh
      Nd = 0;   # chislo dvoetochij
      Nt = 0;   # chislo tochek s zapyatoj
}

{
 for( i = 1; i <&lt;= NF; i++ ){
      if( $i ~ /,$/ ) {
               Np++;
               Nb--;
      }

      # Nb--; ne uchityvat' v dline
      # slova znak prepinaniya

      if( $i ~ /:$/ ) {
               Nd++;
               Nb--;
      }

      if( $i ~ /;$/ ) {
               Nt++;
               Nb--;
      }

      Nb  += length( $i ); # dlina slova
      Nw++; # uvelichit' chislo slov
 }
}

END    {
      print("CHislo zapyatyh =", Np);
      print("CHislo dvoetochij =", Nd);
      print("CHislo tochek s zapyatoj =", Nt);
      print("CHislo slov =", Nw);
      print("CHislo simvolov v slovah =", Nb);
      print("CHislo predlozhenij =", NR );
      print("Srednyaya dlina predl. =", Nw/NR,"(slov)");
      print("Srednyaya dlina slova =", Nb/Nw);


                           - 25 -










}

Nizhe pokazan rezul'tat raboty programmy:

    CHislo zapyatyh = 6
    CHislo dvoetochij = 5
    CHislo tochek s zapyatoj = 6
    CHislo slov = 50
    CHislo simvolov v slovah = 150
    CHislo predlozhenij = 10
    Srednyaya dlina predl. = 5 (slov)
    Srednyaya dlina slova = 3


6.  Vvod i vyvod dannyh v AWK-programmah


     Vvod dannyh v AWK-programmu opredelyaetsya  imenem  vhod-
nogo  fajla v komandnoj stroke. Takih fajlov mozhet byt' nes-
kol'ko, i obrabatyvat'sya AWK-programmoj oni budut posledova-
tel'no  v tom poryadke, v kotorom ukazany v komandnoj stroke,
naprimer:

    awk  -f prog f1 f2 f3 f4

AWK-programma iz fajla prog budet  vypolnyat'sya  nad  vhodnym
potokom zapisej iz fajlov f1, f2, f3 i f4.  Zdes' neobhodimo
otmetit', chto predopredelennaya  peremennaya  NR  budet  imet'
znachenie,  ravnoe  poryadkovomu nomeru zapisi ( NR ne obnulya-
etsya pri perehode k chteniyu ocherednogo fajla).  Pust' imeyutsya
chetyre fajla. Fajl f1:

    a[1][1]  a[1][2]  a[1][3]  a[1][4]
    a[2][1]  a[2][2]  a[2][3]  a[2][4]
    a[3][1]  a[3][2]  a[3][3]  a[3][4]
    a[4][1]  a[4][2]  a[4][3]  a[4][4]

Fajl f2:

    b[1][1]  b[1][2]  b[1][3]  b[1][4]
    b[2][1]  b[2][2]  b[2][3]  b[2][4]
    b[3][1]  b[3][2]  b[3][3]  b[3][4]
    b[4][1]  b[4][2]  b[4][3]  b[4][4]

Fajl f3:

    c[1][1]  c[1][2]  c[1][3]  c[1][4]
    c[2][1]  c[2][2]  c[2][3]  c[2][4]
    c[3][1]  c[3][2]  c[3][3]  c[3][4]
    c[4][1]  c[4][2]  c[4][3]  c[4][4]

Fajl f4:



                           - 26 -










    d[1][1]  d[1][2]  d[1][3]  d[1][4]
    d[2][1]  d[2][2]  d[2][3]  d[2][4]
    d[3][1]  d[3][2]  d[3][3]  d[3][4]
    d[4][1]  d[4][2]  d[4][3]  d[4][4]

Kazhdyj iz etih fajlov vklyuchaet po chetyre zapisi  (po  chetyre
polya  v  kazhdoj).   Drugimi  slovami,  kazhdyj fajl - matrica
(4*4).  Dopustim, neobhodimo poluchit' novuyu matricu  s  raz-
mernost'yu  (4*4),  stolbcy  kotoroj  sostavleny iz elementov
diagonalej ishodnyh matric. Nizhe priveden tekst programmy, v
kotoroj reshaetsya eta zadacha:

    {
        if( FILENAME != Name ) {
                i = 0;
                Name = FILENAME;
        }


        if( i == 1 ) {
                Dig1 = Dig1 " " $1;
                next;
        }
        if( i == 2 ) {
                Dig2 = Dig2 " " $2;
                next;
        }
        if( i == 3 ) {
                Dig3 = Dig3 " " $3;
                next;
        }
        if( i == 4 ) Dig4 = Dig4 " " $4;
    }

    END     {
            print( Dig1 );
            print( Dig2 );
            print( Dig3 );
            print( Dig4 );
    }


     V programme dva pravila.  Pervoe  pravilo  ne  soderzhit
selektora, sledovatel'no, vypolnyaetsya dlya vseh vhodnyh zapi-
sej.  Vtoroe  pravilo  vypolnyaetsya  po  zaversheniyu  vhodnogo
potoka.  Programma rabotaet sleduyushchim obrazom: pervonachal'no
proveryaetsya, izmenilos' li imya vhodnogo  fajla  (predoprede-
lennaya  peremennaya  FILENAME),  zatem,  esli  ne izmenilos',
prisvaivaetsya znachenie sootvetstvuyushchego polya zapisi k  pere-
mennoj  Dig (ispol'zuetsya operaciya konkatenacii starogo zna-
cheniya Dig so znacheniem polya i prisvaivaniya Dig novogo znache-
niya).  Peremennaya  Name  prednaznachena  dlya sohraneniya imeni
vhodnogo fajla. Pervonachal'no znacheniya peremennyh Name i Dig


                           - 27 -










ravny  pustym strokam. Vazhno, chto my znaem tochno chislo zapi-
sej, eto pozvolyaet vydelyat' nuzhnye polya v  zapisyah.   Dopus-
tim, vypolnyaetsya sleduyushchaya komandnaya stroka:

    awk -f prog  f1 f2 f3 f4 >&gt; Result

v fajle Result budem imet':

    a[1][1] b[1][1] c[1][1] d[1][1]
    a[2][2] b[2][2] c[2][2] d[2][2]
    a[3][3] b[3][3] c[3][3] d[3][3]
    a[4][4] b[4][4] c[4][4] d[4][4]

Rezul'tat raboty programmy  sushchestvenno  svyazan  s  poryadkom
chteniya vhodnyh fajlov. Esli vypolnit' komandnuyu stroku

    awk -f prog  f4 f3 f2 f1 >&gt; Result

poluchim:

    d[1][1] c[1][1] b[1][1] a[1][1]
    d[2][2] c[2][2] b[2][2] a[2][2]
    d[3][3] c[3][3] b[3][3] a[3][3]
    d[4][4] c[4][4] b[4][4] a[4][4]


     Kogda voznikaet neobhodimost' peredat' v  AWK-programmu
znacheniya nekotoryh peremennyh, mozhno vospol'zovat'sya vozmozh-
nost'yu ukazat' ih v fajle.  Dopustim,  zaranee  ne  izvestny
obrazcy  dlya vydeleniya zapisej fajla f1. V etom sluchae mozhno
sozdat' fajl f0 s opisaniyami  obrazcov  i,  vospol'zovavshis'
znacheniem  peremennoj  FILENAME,  prisvoit'  etim peremennym
nuzhnye znacheniya. Pust' fajl f0 imeet vid:

    aaa bbb ccc

Pust' fajl f1 imeet vid:

    aaa bbb ccc ddd eee
    eee bbb ccc ddd aaa
    aaa fff ccc ddd eee
    aaa bbb ggg ttt eee

Programma na AWK:











                           - 28 -










    FILENAME == "f0" {
            pat1 =  $1;
            pat2 =  $2;
            pat3 =  $3;
            next;
    }

    $1 == pat1 { print; next }
    $2 == pat2 { print; next }
    $3 == pat3 { print }

Posle vypolneniya komandnoj stroki

    awk -f prog f0 f1

poluchim v fajle Result:

    aaa bbb ccc ddd eee
    aaa fff ccc ddd eee
    aaa bbb ggg ttt eee


     Mozhno predusmotret'  vvod  peremennyh  so  standartnogo
vvoda;  vospol'zuemsya tem, chto peremennaya FILENAME dlya stan-
dartnogo vvoda opredelena kak "-".  Pust' fajl f1 imeet vid:

    aaa bbb ccc ddd eee
    eee bbb ooo ddd aaa
    aaa fff ccc ddd eee
    qqq bbb ggg ttt eee
    ooo fff ggg ttt eee
    ccc bbb ggg ttt eee

Privedennaya nizhe programma pozvolyaet poluchit' znacheniya pere-
mennyh s klaviatury displeya:

    BEGIN   { print("Vvodite znacheniya polej:"); }

    FILENAME == "-" {
            pat1 =  $1;
            pat2 =  $2;
            pat3 =  $3;
    }

    FILENAME == "f1" {
            if($1 == pat1) { print($0); next }
            if($2 == pat2) { print($0); next }
            if($3 == pat3) { print($0);}
    }

Posle zapuska na vypolnenie sleduyushchej komandnoj stroki

    awk -f prog - f1


                           - 29 -










programma budet zhdat' vvoda s klaviatury displeya  (zavershit'
vvod neobhodimo simvolom konec fajla - CTRL/D). Naprimer:

    Vvodite znacheniya polej:
    qqq fff ooo
    CTRL/D
    eee bbb ooo ddd aaa
    aaa fff ccc ddd eee
    qqq bbb ggg ttt eee
    ooo fff ggg ttt eee


     Kak uzhe govorilos' ran'she, vyvod AWK-programmy  naprav-
lyaetsya  na  ekran  displeya,  esli  ne  bylo  ukazano drugoe.
Sushchestvuet vozmozhnost' napravit' vyvod po neskol'kim kanalam
neposredstvenno iz AWK-programmy, dlya etogo mozhno vospol'zo-
vat'sya standartnymi sredstvami sistemy DEMOS.  Naprimer:

    print( $0 ) >&gt; "file";

zapis' budet napravlena v fajl s imenem ./file;

    print( $0 ) >&gt;>&gt; "file";

zapis' budet dopisana v ./file;

    print( $0 ) >&gt; $2;

zapis' budet napravlena v fajl s imenem, ravnym  soderzhimomu
ee vtorogo polya.

     Sushchestvuet vozmozhnost' iz AWK-programmy napravit' vyvod
v konvejer, naprimer:

    {
       print($0) | "tr ' ' '\n' | sort ";
    }

Zdes' zapis' budet napravlena komande  tr,  kotoraya  zamenit
probel simvolom '\n', zatem otsortirovana komandoj sort.

     Pust' vypolnena sleduyushchaya komandnaya stroka:

    awk -f prog -

posle vvoda s klaviatury neskol'kih zapisej

    dfa nrk klm njf rty xvz
    saa ass dcf vfr klm ttr
    CTRL/D

poluchim:



                           - 30 -










    ass
    dcf
    dfa
    klm
    klm
    njf
    nrk
    rty
    saa
    ttr
    vfr
    xvz

Vyvod rezul'tata raboty konvejera osushchestvlyaetsya po zavershe-
niyu  chteniya poslednej vhodnoj zapisi. Kanal vyvoda v primere
sovpadaet s kanalom standartnogo vyvoda, no ego mozhno  pere-
opredelit' na lyuboj fajl.

     V odnoj  AWK-programme  mozhno  odnovremenno  opredelit'
neskol'ko  kanalov  vyvoda,  chislo  kotoryh zavisit ot chisla
fajlov, razreshennyh dlya  odnovremennogo  ispol'zovaniya.  |to
chislo  ustanavlivaetsya  pri  generacii  operacionnoj sistemy
DEMOS.

     Dlya vyvoda dannyh v AWK-programme prednaznachen operator
print.   Do  nastoyashchego momenta my primenyali lish' odnu formu
ispol'zovaniya etogo operatora:

    print(spisok_fakticheskih_parametrov);

Kruglye skobki ispol'zovalis' ran'she dlya togo, chtoby ne otv-
lekat'  chitatelya,  znakomogo s yazykom programmirovaniya Si, -
ih mozhno ne ukazyvat'. Sushchestvuyut i drugie formy ispol'zova-
niya etogo operatora:

print;
     vyvoditsya vsya zapis';

print $1, $2;
     znacheniya polej vyvodyatsya cherez probel;

print $1 $2;
     vyvoditsya konkatenaciya znachenij polej.


     Pri  neobhodimosti  upravleniya  formatom  vyvoda  mozhno
ispol'zovat'   bibliotechnuyu   funkciyu  printf,  sintaksis  i
rezul'tat raboty  kotoroj takie zhe, kak i v yazyke Si.

7.  Ispol'zovanie vstroennyh funkcij





                           - 31 -










     Interpretator awk vklyuchaet  nabor  vstroennyh  funkcij,
kotorye  mozhno  ispol'zovat' v dejstviyah pravil.  Sushchestvuyut
dva sposoba vyzova vstroennyh funkcij:

    imya_funkcii(spisok_fakticheskih_parametrov)

    imya_funkcii

Vo vtorom sluchae v kachestve fakticheskogo parametra  primenya-
etsya  vsya tekushchaya zapis'. Kak obychno, znachenie funkcii pods-
tavlyaetsya v vyrazhenie v tom meste, gde opredelen vyzov.

     Imeyutsya sleduyushchie vstroennye funkcii:

length(vyrazhenie)
     znacheniem vyrazheniya yavlyaetsya  stroka.   Funkciya  length
     vozvrashchaet dlinu stroki, naprimer:

         print( length($1 " " $2));

     budet napechatana dlina stroki, poluchennoj konkatenaciej
     polya  $1, probela i polya $2.  Forma bez argumenta vozv-
     rashchaet dlinu zapisi.

exp(vyrazhenie)
     vozvrashchaet eksponentu ot vyrazheniya.

log(vyrazhenie)
     vozvrashchaet natural'nyj logarifm vyrazheniya.

sqrt(vyrazhenie)
     vozvrashchaet znachenie kvadratnogo kornya ot vyrazheniya.

int(vyrazhenie)
     vozvrashchaet celuyu chast' chisla, ravnogo znacheniyu  vyrazhe-
     niya.

substr(S, M, N)
     vozvrashchaet chast' stroki S, nachinayushchuyusya ot pozicii M  i
     imeyushchuyu  dlinu  ne bolee N simvolov. Simvoly v stroke S
     numeruyutsya s 1.  Esli argument N ne ukazan,   vozvrashcha-
     yutsya vse simvoly ot M do konca stroki.

         string = substr( $0, 12, 20);

     String budet vklyuchat' 9 simvolov (s 12 po  20)  tekushchej
     zapisi.

index(As, Ps)
     vozvrashchaet nomer pozicii, s kotoroj stroka Ps sovpadaet
     so strokoj As. Esli sovpadeniya net, vozvrashchaetsya 0.




                           - 32 -










sprintf(format, vyrazhenie, ...)
     vozvrashchaet stroku,  vyvedennuyu  po  formatu.  Sintaksis
     funkcii i rezul'tat raboty analogichny funkcii sprintf v
     biblioteke yazyka programmirovaniya Si.

split( S, Name, razdelitel' )
     stroka S razbivaetsya na polya, znacheniya kotoryh prisvai-
     vayutsya  elementam  massiva Name. Znacheniem pervogo ele-
     menta  Name[1]  budet  soderzhimoe  pervogo  vydelennogo
     polya,  znacheniem  vtorogo  elementa  Name[2]  - vtorogo
     vydelennogo polya i tak dalee.  Esli ne ukazan  razdeli-
     tel'   polej,  ispol'zuetsya  znachenie  predopredelennoj
     peremennoj FS.  Funkciya split vozvrashchaet chislo vydelen-
     nyh polej. Rassmotrim primer.  Pust' imeetsya fajl f1

         aaa bbb ccc# ddd# eee fff# ggg
         ttt# ggg eee# ccc ddd sss# yyy

     i AWK-programma

         {
           i = split( $0, Name, "#");
           for(j = 1; j <&lt;= i; j++)
               print( "Name["j"] =", Name[j]);
         }

     posle vypolneniya komandnoj stroki

         awk -f prog f1

     poluchim:

         Name[1] = aaa bbb ccc
         Name[2] =  ddd
         Name[3] =  eee fff
         Name[4] =  ggg
         Name[1] = ttt
         Name[2] =  ggg eee
         Name[3] =  ccc ddd sss
         Name[4] =  yyy















                           - 33 -










                         SODERZHANIE



    Annotaciya .........................................    2

1.  Principy raboty interpretatora awk ................    3

2.  Peremennye,  vyrazheniya  i   prisvaivaniya   v   AWK-
    programmah ........................................    7

3.  Struktura AWK-programmy ...........................   13

4.  Selektory .........................................   16

5.  Dejstviya ..........................................   22

6.  Vvod i vyvod dannyh v AWK-programmah ..............   26

7.  Ispol'zovanie vstroennyh funkcij ..................   31



































                           - 34 -




Last-modified: Mon, 29 Jun 1998 13:54:11 GMT
Ocenite etot tekst: