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í.