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