Expanze parametrů a proměnných
Základním principem je nahradit jména parametrů (tímto termínem zde budeme označovat proměnné a poziční i speciální parametry) jejich hodnotou. Bash to udělá vždy, když před jméno parametru uvedeme znak dolar, např. $PATH, $1. Jak jsme si ale ukázali už dříve, je vhodné jména parametrů balit do složených závorek, aby nedošlo k jejich splynutí s okolním textem. Třeba místo echo $cestabin/skript se jistě hodí spíše echo ${cesta}bin/skript.
Vedle prostého nahrazení jména parametru jeho hodnotou má však Bash v rukávu (či spíše ve složených závorkách) ještě tyto užitečné funkce:
${parametr:-slovo}
- za normálních okolností vypíše prostě hodnotu parametru (proměnné), ale pokud je tento prázdný, vypíše místo toho slovo (řetězec) uvedený za dvojtečkou a pomlčkou. Např. můžeme zadat echo "Desktop: "${DESKTOP:-žádný}
a Bash vypíše jméno pracovní plochy uživatele nebo slovo "žádný", pokud uživatel pracuje mimo grafiku.
${parametr:=slovo}
- funguje velmi podobně jako varianta s mínusem, takže také vypíše hodnotu parametru a, pokud je tento nulový (nenastavený), zobrazí místo něj zadaný řetězec (slovo). Přitom ale zároveň změní hodnotu parametru tak, že do něj dané slovo vloží.
${parametr:?slovo}
- další obdoba první varianty s tím, že slovo se vypíše v případě nulové hodnoty parametru, ne však jako běžný, nýbrž chybový výstup. Pokud to nastane v neinteraktivním shellu (např. při provádění skriptu), bude shell (i skript) ukončen.
${parametr:+slovo}
- a do čtvrtice zde máme opak mínusu. Pokud je parametr nulový nebo nenastavený, nic se nestane. Pokud však nějakou hodnotu obsahuje, zobrazí se slovo.
${parametr:offset}
- velké překvapení mne čekalo, když jsem za jméno proměnné zadal dvojtečku a nějaké malé číslo. Bash v takovém případě uřízne zadaný počet znaků ze začátku vypisovaného řetězce. Např. echo ${SHELL}
vypíše /bin/bash, zatímco echo ${SHELL:5}
jen bash, protože prvních 5 znaků ubral.
${parametr:offset:delka}
- pokud vám nestačí řezat pouze od začátku, můžete přidat další dvojtečku a za ni počet znaků, které chcete od offsetem zadaného místa zobrazit (nikoli uřezat zezadu). echo ${SHELL:5:2} potom ukáže jen "ba", tedy šestý a sedmý znak hodnoty $SHELL.
${!prefix*}
- zobrazí seznam jmen proměnných, která začínají na zadaný prefix. Chceme-li zjistit, jak egocentrický je Bash, pomůže nám v tom echo ${!BASH*}, vypisuje všechny proměnné se jménem začínajícím slovem BASH. Stejnou funkci plní ${!prefix@}.
${!jmeno[*]}
- vypíše seznam položek pole (viz 5. díl seriálu). Zdůrazňuji seznam jmen položek, nikoli hodnot (to by udělalo echo ${jmeno[*]}). Jména položek (tj. označení v hranaté závorce) nemusí nabývat jen číselných hodnot, takže můžeme mít třeba pole pc[lin]=10, pc[bsd]=3, pc[win]=0.
${#parametr}
- udává délku parametru ve znacích, takže echo ${#SHELL} nám dá 9. ${#*} a ${#@} ale zobrazí počet pozičních parametrů. Obdobně ${#jmeno[*]} udává počet položek zadaného pole (echo ${#pc[*]} z předchozího bodu by vrátilo 3).
${parametr#slovo}
a ${parametr##slovo}
- slouží k uřezávání začátku hodnoty parametru, ne však podle délky (jako u offsetu), ale přímo zadaným řetězcem. Tento řetězec může navíc obsahovat zástupné znaky (*, ? apod.) Jedna mřížka značí co nejkratší řezání, dvě mřížky naopak co nejdelší. Kupř. echo ${PATH#*:} uřízne všechno od počátku řetězce až po první dvojtečku (včetně). Naopak echo ${PATH##*:}
vezme vše až po poslední výskyt dvojtečky v seznamu cest.
${parametr%slovo}
a ${parametr%%slovo}
- obdoba předchozího, ale řeže se od konce. Abychom si to ukázali opět prakticky, použijeme speciální parametr $0, což by měla být cesta k aktuálnímu shellu (např. /bin/bash). echo ${0%b*}
ukáže /bin/, protože celé slovo bash smazalo. Varianta echo ${0%%b*}
vypíše jen /, protože smazala vše od prvního výskytu b.
${parametr/vyraz/retezec}
- a to nejlepší nakonec. Bash umí v řetězcích nahrazovat určený výraz zadaným řetězcem. Řekněme, že chceme při zobrazení zvýraznit všechny výskyty bin v proměnné PATH velkými písmeny. Pak zadáme echo ${PATH/bin/BIN}
. Chyba? Že se vám zvýraznil jen první výskyt? Máte pravdu. Pro náhradu všech musíme první lomítko zdvojit (echo ${PATH//bin/BIN}
). Vyraz přitom nemusí být jen text, ale může obsahovat zástupné znaky (*,?,[] apod.)
A to je k expanzi proměnných asi tak všechno. Je to mocná zbraň. Může vám ušetřit mnoho volání externích aplikací typu cut, sed nebo awk. A mocnější je ještě více, když si uvědomíme, že za výrazy a slova nemusíme dosazovat jen konkrétní řetězce, ale proměnné (např. echo ${PATH:$odstup:$delka}
). Příště nám čeká mimo jiné počítání, tak si raději za domácí úkol zopakujte malou násobilku.