Skriptovanie v shelli: Expanzia premenných

Pokročilá expanzia premenných

S expanziou premenných sa dajú robiť všakovaké triky. Chcete získať hodnotu premennej a ak nie je definovaná, použiť implicitnú hodnotu?

echo ${NEDEFINOVANA_PREMENNA:-N/A}

Toto, prirodzene, vypíše

N/A

Ak máme výraz ${parameter:-slovo}, znamená to:

Ak je parameter nastavený a nenullový (t. j. má nenulovú dĺžku), vráť jeho hodnotu. Ak je parameter nastavený, ale nullový, alebo nie je vôbec nastavený, expanduj na slovo.

Skript z predošlej úlohy môžeme upraviť na predbežnú verziu:

#!/bin/sh
LOGIN=${1:-novotnyr}
cut -d":" -f6 < /etc/passwd | grep "$LOGIN"

Ak nedodáme parameter príkazového riadka, do premennej LOGIN sa priradí novotnyr. Keby sme chceli správanie vylepšiť, máme dve možnosti.

Expanzia na hodnotu po spustení skriptu

Samotné slovo tiež podlieha expanzii. Môžeme teda urobiť trik: v mnohých verziách Linuxu existuje premenná USER obsahujúca login aktuálneho používateľa:

#!/bin/sh
LOGIN=${1:-$USER}
cut -d":" -f6 < /etc/passwd | grep "$LOGIN"

Ak 1 nie je definovaná, nahradí sa expanziou $USER, teda hodnotou aktuálneho používateľa.

Ak chceme byť bezpeční, môžeme využiť

LOGIN=${1:-$(id -un)}

Ak 1 nie je definovaná, nahradí sa expanziou $(id -un). V subshelli sa pustí tento príkaz a výsledok sa použije v expanzii.

Zlyhanie v prípade nedefinovanej premennej

Ak použijeme výraz ${parameter:?slovo}, znamená to:

Ak je parameter nastavený a nenullový (t. j. má nenulovú dĺžku), vráť jeho hodnotu. Ak je parameter nastavený, ale nullový, alebo nie je vôbec nastavený, ukonči skript s chybou a vypíš na chybový výstup slovo.

Ukážka:

#!/bin/sh
LOGIN=${1:?Usage: $0 login}
cut -d":" -f6 < /etc/passwd | grep "$LOGIN"

Ak je premenná 1 nedefinovaná, skript skončí s chybou a vypíše sa napr.

./homedir.sh: line 2: 1: Usage: ./homedir.sh login

Špeciálna premenná 0

Shell dáva k dispozícii špeciálnu premennú 0, ktorá obsahuje meno aktuálne spúšťaného skriptu. S výhodou ho môžeme použiť pri navedení používateľa na správne spustenie skriptu.

Práca s reťazcami

Shell dáva k dispozícii niekoľko expanzií, ktoré umožňujú prácu s podreťazcami jednoduchším spôsobom než cez sed.

Sekanie prefixov

Ak sa nachádzame v /home/novotnyr a chceme odseknúť /home, stačí:

echo ${PWD#/home}

Výsledkom budem

/novotnyr

Operátor # odsekne najkrajší prefix, ktorý sa zhoduje so vzorom uvedeným za ním.

Sekanie najdlhších prefixov

Modifikátor ## (dve mreže) odsekáva najdlhší prefix, čo má zmysel hlavne v kombinácii s patternmi v shelli (tými, ktoré sa používajú v globbingu). Výraz */ zachytí ľubovoľný reťazec ukončený lomkou, čo sa dá použiť v odsekávaní adresárovej cesty

Ak echo $PWD vráti /home/novotnyr/public_html, potom:

echo ${PWD##*/}

vráti

public_html

To je prakticky ekvivalentné príkazu basename.

V porovnaní s tým jednomrežová verzia odsekne najkrajšiu zhodu, teda „všetko po prvú lomku”:

echo ${PWD#*/}

vráti

home/novotnyr/public_html

Sekanie sufixov

Takisto možno sekať aj [najkrajšie] sufixy pomocou % (mnemotechnicky: mreža je vľavo, seká predpony, percento vpravo, seká prípony).

Ak echo $PWD vráti /home/novotnyr/public_html, potom:

echo ${PWD%/public_html}

vráti

public_html 

Najdlhšie sufixy odsekneme cez %%.

Dĺžka reťazca

Potrebujete analógiu strlen()? Stačí použiť mrežu:

MENO="Jozef"
echo ${#MENO}

A výsledok bude 5.

Ostatné expanzie

Shell podporuje aj ďalšie špeciálne expanzie. Garantovaným základom sú možnosti uvedené v POSIXovej norme, ale Bash dáva k dispozícii ešte viac možností.

Pridaj komentár

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *