21Kapitola

Bash 21: Práce s textovými řetězci

Minule jsme si udělali přehled o zajímavé oblasti zvané rozšiřování neboli expanze. Jedním z typů expanzí bylo rozšíření parametrů a proměnných. To mimo jiné umožňuje práci s textovými řetězci přímo na úrovni Bashe. Této problematice se dnes budeme věnovat podrobněji.

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.