Programavimas Unix aplinkoje

Šis straipsnelis pratęsia puslapį Unix komandinės eilutė  
o tęsinys - Veikimo valdymas Unix skriptuose  

Pravartu paskaityti apie programavimo kompiuteriams palyginimą su kitais realaus gyvenimo aprašais > >>>>

Įvadiniame straipsnelyje pateikėme pagrindines žinias apie komandinės eilutės interpretatorius bei pačią komandinę eilutę. Tad, kilus neaiškumams (pvz., apie komandinės eilutės interpretatorius), pasitikslinkite tą puslapį. O čia toliau tęsime „pamokas“ apie programavimą Unix aplinkoje.

Visi čia pateikiami pavyzdžiai buvo patikrinti Aix 6.1.8.0 aplinkoje (tačiau, iš esmės, jie turėtų tikti ir Linux). Orientavomes, kad jie tiktų Bourne interpretatoriui (sh), - tačiau, jei pavyzdžiai arba aptariami klausimai skirti kitiems interpretatoriams (paprastai, tai bash), tai atskirai nurodoma.

Unix kintameji

Kintamieji yra atminties sritys, kurioms suteikti vardai. Kintamasis apibrėžiamas jam pirmąjį kartą priskiriant reikšmę. Reikšmę galima priskirti naudojant priskyrimo operatorių ( = ) arba typeset komandą. Kintamajam galima ir nepriskirti reikšmės (kaip pavyzdyje kintamajam vykimo_vieta, tada jo reikšmė yra null. Panaudojant kintamąjį, prieš jo vardą prirašomas dolerio ženklas, pvz., $vykimo_vieta

Lokaliųjų kintamųjų reikšmės pasiekiamos tik tose funkcijose arba sub-apvalkaluose, kuriuose jie apibrėžti. Globalieji kintamieji prieinami visose apvalkalo srityse. Lokaliuosius kintamuosius galima padaryti globaliaisiais su export komanda. Pvz., globaliųjų kintamųjų apibrėžimai ir priskyrimai:

maximal_discount=50
export maximal_discount
nuolaida = $maximal_discount

typeset distance_km=500
export  distance_km 
echo "Atstumas: " $distance_km

vykimo_vieta=
export vykimo_vieta

Pastaba: bash interpretatoriuje typeset taip pat užrašoma ir kaip declare.

Kintamojo atšaukimui skirta komanda unset, pvz.
unset nuolaida

Lokalų kintamąjį galima apibrėžti komanda local (bash interpretatoriuje ji leidžiama tik funkcijose) – nurodant, kad kintamasis galioja tik lokaliame kontekste, pvz.,

#!/bin/bash
vidurkis () {
   local viso=0;
   // ...
   return $viso;
}

Duomenų tipai

Simbolių eilutes, turinčias tarpų ir specialiųjų ženklų, galima paimti „į kabutes“. Leidžiamos šie kabučių tipai: viengubos ('') - leidžia gaubti visus simbolius; dvigubos ("") - jose interpretuojami simboliai $ ir \; atvirkščios (``) - komandos vykdymui apgaubimui. Vieno tipo kabutės gali būti panaudotos tekste, apgaubtame kito tipo kabutėse. Jų panaudojimo pavyzdžiai:

echo "Atstumas: $distance_km"
echo 'Atstumas: $distance_km'
echo `echo $distance_km`

Gausime tokį rezultatą:

Atstumas: 567
Atstumas: $distance_km
567

Leidžiama kintamuosius apibrėžti panaudojant duomenų tipus, pvz., galima nurodyti, kad kintamasis N įgaus sveikų skaičių reikšmes, o kintamasis sPreke turės tekstinę reikšmę.

Tai turi prasmę ir todėl, kad aritmetiniai veiksmai su skaitiniais kintamaisiais atliekami greičiau. Dauguma apvalkalų leidžia naudoti 4 duomenų tipus:

  • simbolių sekas (tekstines reikšmes);
  • sveikuosius skaičius;
  • skaičius su slankiu kableliu (dešimtainius skaičius);
  • masyvus (kintamųjų sekas).

Kintamieji apvalkaluose:
Bourne apvalkalas – tik simbolių eilutės; ir visi kintamieji yra globalūs;
Bash apvalkalas - simbolių eilutės ir sveikieji skaičiai. Leidžiama apibrėžti tik lokaliuosius kintamuosius;
TC apvalkalas – leidžia visus 4 minėtus kintamųjų tipus. Kintamieji gali būti tiek lokalūs, tiek globalūs;
Korn apvalkalas - leidžia visus 4 minėtus kintamųjų tipus. Kintamieji gali būti tiek lokalūs, tiek globalūs

Bet kuris kintamasis gali turėti vieną ar kelis atributus, nusakančius, kaip kintamasis saugomas, pasiekiamas ir pavaizduojamas. Pvz., atributas integer nurodo, kad kintamasis yra sveiko tipo skaičių, o left justify – kad eilutė yra kairinio lygiavimo. Leistini šie atributai:
-i – sveiko tipo kintamasis;
-E ir -F – slankaus kablelio skaičių kintamasis;
-u ir -l - eilutė didžiosiomis ir mažosiomis raidėmis;
-R ir -L – eilutė lygiuojama į dešinę ir kairę;
-RZ ir LZ - eilutė lygiuojama į dešinę ir kairę pridedant arba šalinant nulius;
-x – autoeksportuojamas (globalusis) kintamasis;
-r – kintamojo reikšmė tik skaitymui (draudžiama ją keisti – priskirti reikšmę sukelia klaidą)

Ženklas „-“ nurodo įjungti atributą, o „+“ - nuimti atributą, pvz.,

typeset -i distance_km=555
typeset +i distance_km

Jei atributų prasmės neprieštaringos, galima atributus jungti vienoje typeset komandoje, pvz. (Korn apvalkale):

typeset -uLx vykimo_vieta=Vilnius
echo $vykimo_vieta

Atsakymas bus
VILNIUS

typeset komanda vien su atributu į ekraną pateikia visų kintamųjų, turinčių tą atributą, sąrašą. Pvz., žemiau esanti komanda, pateiks (tarp kitų) ir vykimo_vieta kintamąjį (su jo reikšme):

typeset -u

Parametrai

Parametrai yra apvalkalo rezervuoti kintamieji, leidžiantys valdyti apvalkalo aplinką arba gauti informaciją apie vykstančius procesus. Aplinkos kintamieji yra apibrėžiama vartotojo profilio faile (.profile, esančiame „šakniniame“ vartotojo kataloge). Vartotojas savo kode negali kitoms reikmėms naudoti rezervuotų kintamųjų. Štai keli aplinkos kintamieji:
SHELL – nutylimasis vartotojo apvalkalas;
HOME – vartotojo „šakninis“ katalogas;
PATH – kelias, pagal kurį ieškoma komandų vykdymui

Apvalkalai turi ir keletą specialių parametrų, pvz.:
? - paskutinės vykdytos komandos baigimo kodas (sėkmingo įvykdymo atveju – 0);
- - apvalkalui nustatyti režimai;
! - paskutinės fone vykdomos komandos arba sub-proceso ID;
$ - veiksnaus apvalkalo proceso ID;
PPID - veiksnaus apvalkalo tėvinio proceso ID;
ERRNO – paskutinio nsėkmingo kreipinio į sistemą klaidos kodas (parametras priklausomas nuo platformos ir galimas ne visose sistemose)

Pvz.,

echo $? 
echo $- $$

Poziciniai parametrai gali turėti argumentus, perduodamus komandai, skriptui ar funkcijai. Jie apibrėžiami pagal eilės numerį komandinėje eilutėje: 0 – komandos pavadinimas, 1 – pirmasis argumentas ir t.t. Pvz., komandai

ls -a /usr/home

0 parametras įgys reikšmę “ls“;
1 - “-a”;
2 - “/usr/home”

$* gražina visų pozicinių parametrų reikšmes, atskirtas tarpais.
$# gražina visų pozicinių parametrų kiekį (pvz., ankstesniam pavyzdžiui su funkcija ši reikšmė būtų 2).

Poziciniai parametrai ypač naudingi funkcijose (jos bus aprašomos tolimesniuose straipsneliuose), pvz.,

renameFN () {
  oldFN=$1;
  newFN=$2;
  mv $oldFN $newFN;
}
  
renameFN a.txt b.txt

Betarpiškai galite nurodyti 0-9 pozicinius parametrus. Jei reikia pasiekti didesnių numerių parametrus, turi naudoti riestinius skliaustus, pvz., ${10}. Analogiškai galima atskirti kintamąjį nuo likusio teksto. Prieš kintamojo pavadinimą panaudojus diezą (#), sužinosime kintamojo reikšmės ilgį, pvz.,

firma=”Trys vilkai”
echo ${firma}-ilgis: ${#firma}

Rezultatas:
Trys vilkai-ilgis: 11

Reikšmių perdavimas per parametrus labai naudingas, tačiau dirbti su poziciniais parametrais nėra intuityvu. getops funkcionalas leidžia tą darbą palengvinti.

Ši komanda paima kitą komandinės eilutės argumentą ir patikrina, ar jis prasideda minuso (-) ženklu. Jei taip, tada bando pirmąjį po minuso ženklą sutapatinti su pateiktu vienos raidės variantų sąrašu, kuris pateikiamas kaip pirmasis getops parametras. Jei randamas atitikmuo, ir po tos raidės seka dvitaškis (:), getopts bando paimti to parametro reikšmę. Ji nuo pasirinkimo gali būti atskirta tarpu. Antruoju getopts parametru nurodytam parametrui priskiriama pasirinkimo raidė, o OPTARG kintamajam priskiriama parametro reikšmė. Kintamajam OPTIND priskiriamas kitas komandinės elutės parametras.

Jei pasirinkimas nesurastas, komandoje esančiam kintamajam priskiriama ? ir pateikiamas klaidos pranešimas.

Kai visi parametrai praeiti, getorgs gražina ne nulinę reikšmę arba false, kurią galima panaudoti patikrinimui, ar viskas apdorota.

Pvz.,

cmd –f failovardas –v –o operacija

getopts ” v f : o : ” pasirinkimas

O žemiau pateikiamas pavyzdys atpažįsta –i ir –f parametrus su failo vardais, o taip pat -v ir –c parametrus be reikšmių. Pabaigoje išvedamas likusieji parametrų (paprastai tai failų vardai) – o apie veiksmų sekos valdymą bus detaliai parašyta vėlesniuose straipsneliuose..

while getopts "i:o:vc" pasirinkimas
do
  case $pasirinkimas in
     (i) inf=$OPTARG;;
     (o) outf=$OPTARG;;
     (v) verv=true;;
     (c) cnt=true;;
     (?) echo "Klaidingas parametras - baigiam"; exit 2;;
  esac
done

echo "xxx $inf";
if [[ -z $inf ]]
then
  echo "Pradinis failas yra privalomas - baigiam";
  exit 1;
fi

shift $(($OPTIND-1))
printf "Liko parametrai: %s\n" "$*"

Kintamojo panaudojimo plėtiniai

O tokie kintamojo “išplėtimai“ leidžia nurodyti pagrindines ir alternatyvias nutylimąsias kintamųjų reikšmes:
${kintamasis:-eilutė} – kintamojo turima reikšmė. Jei kintamajam reikšmė nepriskirta – pateikiama „eilutė“;
${kintamasis:=eilutė} – kintamojo turima reikšmė. Jei kintamajam reikšmė nepriskirta, jam priskiriama „eilutė“;
${kintamasis:+eilutė} - jei kintamajam priskirta reikšmė, pateikiama „eilutė“, o jei ne – niekas nepateikiama (tuščia);
${kintamasis:?eilutė} - kintamojo turima reikšmė. Jei kintamajam reikšmė nepriskirta – pateikiama „eilutė“ ir apvalkalas nutraukia darbą;
${kintamasis:?} - kintamojo turima reikšmė. Jei kintamajam reikšmė nepriskirta – pateikiamas standartinis klaidos pranešimas ir apvalkalas nutraukia darbą;

O taip galima paimti tekstinių eilučių fragmentus:
${kintamasis:pradžia} – eilutės galas pradedant nurodyta pozicija (skaičiuojant nuo 0);
${kintamasis:pradžia:ilgis} – eilutės nurodyto ilgio iškarpa pradedant nurodyta pozicija (skaičiuojant nuo 0);
${kintamasis#šablonas} – eilutė su rastu, ieškant iš kairės, pašalinta trumpiausia šabloną tenkinančia eilutės dalimi;
${kintamasis##šablonas} – eilutė su rastu, ieškant iš kairės, pašalinta ilgiausia šabloną tenkinančia eilutės dalimi;
${kintamasis%šablonas} – eilutė su rastu, ieškant iš dešinės, pašalinta trumpiausia šabloną tenkinančia eilutės dalimi;
${kintamasis%%šablonas} – eilutė su rastu, ieškant iš dešinės, pašalinta ilgiausia šabloną tenkinančia eilutės dalimi;

Pavyzdžiai:

testas="vienas nereikalingas zodis"
echo ${testas:7}
echo ${testas:7:13}
echo ${testas#*ne*}
echo ${testas##*as}
echo ${testas%*ne*}
echo ${testas%%as*}

Rezultatai:

nereikalingas zodis
nereikalingas
reikalingas zodis
zodis
vienas
vien

Formatai šablono paieškai ir pakeitimui:
${kintamasis/šablonas/pakaitalas} – pirma surasta šablono reikšmė pakeičiama pakaitalu;
${kintamasis/šablonas//pakaitalas} – visos surastos šablono reikšmės pakeičiama pakaitalu;
${kintamasis/šablonas#pakaitalas} – pirma surasta šablono reikšmė pakeičiama pakaitalu, jei reikšmė prasideda šablonu;
${kintamasis/šablonas%pakaitalas} – paskutinė surasta šablono reikšmė pakeičiama pakaitalu, jei reikšmė baigiasi šablonu

Pvz.,

echo ${testas/vienas/antras}
echo ${testas/is/elis}

Rezultatai:

antras nereikalingas zodis
vienas nereikalingas zodelis

Masyvai

Masyvai yra kintamieji saugantys reikšmių seką. Masyvo elementų numeracija prasideda nuo 0. Masyvas sukuriamas priskiriant reikšmę jo elementui. Jei kintamasis jau turi (skaliarinę) reikšmę, ši paverčiama masyvo elementu, pvz.

metai="Sausis"
metai[1]="Vasaris"
echo ${metai[0]}

Rezultatas:
Sausis

Masyvo tipo kintamąjį galima sukurti ir komanda:
typeset -a pavadinimas

Indeksams galima naudoti aritmetines išraiškas, pvz.

metai[2+3]="Liepa"
echo ${metai[5]}

Kai naudojama nuoroda į masyvo elemento reikšmę, išraiška turėtų būti echo ${pavadinimas[n]}tam, kad būtumėm tikri, kad ji bus išplėsta teisingai. Pvz.,

pavadinimas[5]="tekstas"
echo $pavadinimas[5]
echo ${pavadinimas[5]}

Rezultatas:

[5]
tekstas

Masyvų kintamiesiems leidžiami tokie panaudojimo formatai:
${masyvas[*]} - išvardijami visi masyvo elementai;
${!masyvas[*]} - išvardijami visi iniciuoti masyvo elementai;
${!masyvas[*]:n} - išvardijami visi masyvo elementai pradedant n-tuoju;
${!masyvas[*]:n:x} - išvardijami x masyvo elementų pradedant n-tuoju;
${#masyvas[*]} - masyvo elementų kiekis;
${#masyvas[n]} - masyvo elementų kiekis apribotas pamasyviu n;

Pvz.,
echo ${#pavadinimas[*]}
echo ${pavadinimas[*]}

Aritmetika

Skriptai veikia tik su teigiamais sveikaisiais skaičiais. Galima aiškiai aprašyti sveiko tipo kintamąjį (kaip alternatyva typeset -i), pvz. (Korn apvalkale),
integer N=10

Ankstesnėse Unix versijose aritmetinėms išraiškoms reikėjo naudoti expr komandą, pvz.,
N=`expr $N+5`

Naujesnės Unix versijos leidžia naudoti let komandą, pvz.:
let N=N+5

Tačiau išraiška turi būti be tarpų. Jei norite panaudoti tarpus, reikia išraišką paimti į skliaustus, nes kitaip gausime klaidą, pvz.:
let "N = N + 5"

Alternatyva let komandai yra priskyrimo sakinys dvigubuose skliaustuose (ir šiuo atveju galima palikti tarpus, pvz.,
((N = N + 5))

Be pagrindinių aritmetinių operacijų (*, /, +, -) galima rasti dalybos liekaną (%). Numatyti ir inkrementiniai bei dekrementiniai operatoriai (+=, -=, *=, /=), pvz.,

let N*=5

Kintamiesiems galima priskirti neigiamas reikšmes.

Galima naudoti ir logines operacijas: && (ir), || (arba) ir ! (ne). Numatytos ir loginės operacijos pabičiui (bitwise): & (ir), | (arba), ^ (xor) ir ~ (neigimas). Trečias bitinių operacijų tipas yra „postūmiai“ (<<, >>), pvz.,

typeset -i num=27
((num=num>>2))
echo $num
num=27
((num=num<<2))
echo $num

Su rezultatu:

6
108

Yra keletas operatorių palyginimas (==, !=, <, <=, >, >=). Pvz.,

((512 <= 128)
echo $?

pateiks
1
nes išraiška klaidinga.

[  Tęsinys: Veikimo valdymas Unix skriptuose  ]

Ankstesnės "Advanced HTML" skyrelio temos:
Tcl kalba
Unix komandinės eilutė
Ateities kalbos?
JavaScript pradmenys
Didžiųjų duomenų mitas
CGI.pm biblioteka: sausainiai
AWK kalba - sena ir nuolat aktuali
CGI.pm biblioteka: sausainiai
Kaip valdyti piešinių pakrovimo tvarką
Įlįskite į lankytojų kailį
Programavimo kalbų istorija
Dygios JavaScript eilutės
Vaizdi rašysena - VB Script
ASP patarimų liūnas
Ruby on Rails

Sveikųjų skaičių žaidimai
Pelė uodega švystelėjo...
Viešojo rakto kriptografija
Programavimo kalbų klegesys
Pirmoji programuotoja: Ada Lovelace
Kaip lankytoją nukreipti į kitą WWW puslapį
JavaScript atspindžiai
Kompiuterių ištakos
Vartiklis