Obsah

Proměnné

Když si potřebujete uložit někam hodnotu, je tu ideální konstrukt proměnná. Jen je tu několik specialit, na které je dobré si dát pozor.

Typ proměnné

bash nemá typy proměnných, proměnné plníte, pracujete s nimi a všichni včetně interpretu doufají, že se nebudete snažit s řetězcem násobit atp. Když na tom budete trvat, pak můžete typ proměnné nadefinovat nebo omezit pomocí příkazu declare nebo typeset. Ale většina lidstva prožije plnohodnotný život bez těchto příkazů.

Jak se bude jmenovat

Jméno proměnné obsahuje ideálně písmena (pouze anglická, pochopitelně, nenapadla vás jiná, že ne), číslice a podtržítka. Jméno by nemělo začínat číslem. Environment proměnné jsou psané velkými písmeny, uživatelské dle chuti.

Environment proměnné

V originále environment variables, v češtině někdy jako proměnné prostředí, jsou proměnné, které už vám někdo vyplnil. Pro každý proces nabývají svých hodnot, například proměnná PWD ukládá hodnotu aktuálního pracovního adresáře, její hodnota se mění po příkazu cd a ačkoli je několik lidí přihlášených k systému, každý má svou proměnnou pro každou svou session.
Seznam a aktuální hodnoty environment proměnných vytiskne příkaz env (zde zkrácený výpis)
jana@drak:~$ env
USER=jana
PWD=/home/jana
HOME=/home/jana
SSH_CLIENT=147.230.89.27 46326 22
LC_ADDRESS=cs_CZ.UTF-8
LC_NUMERIC=cs_CZ.UTF-8
SSH_TTY=/dev/pts/10
MAIL=/var/mail/jana
TERM=xterm-256color
SHELL=/bin/bash
SHLVL=1
LC_TELEPHONE=cs_CZ.UTF-8
LOGNAME=jana
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
XDG_RUNTIME_DIR=/run/user/1000
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
LC_IDENTIFICATION=cs_CZ.UTF-8
LESSOPEN=| /usr/bin/lesspipe %s
_=/usr/bin/env
jana@drak:~$ 
Výpis jsem zkrátila o několik nezajímavých proměnných, s kterými pracovat nebudeme. Povšimněte si, že proměnné jsou všechny psány velkými písmeny.
Proměnná, kterou naplním/změním, je přístupná jenom v rámci jednoho bash procesu – pouze v tom terminálu, který mám spuštěný nebo jenom v rámci běhu jednoho skriptu. Pokud ji chci dostat do podřízených procesů, je potřeba ji exportovat příkazem export. Příklad může být
export a=42
naplní proměnnou a hodnout 42 a exportuje ji. Když si teď vytisknete enviromenální proměnné env, najdete v nich řádek a=42.

Parametry skriptu

Když spustíte skript, jeho jméno se uloží jako proměnná $0. Cokoli napíšu jako parametr skriptu, uloží se jako proměnná $1, $2, atd. Je to jeden z velmi dobrých způsobů, jak předat skriptu nějakou informaci.
K takto uloženým parametrům můžete přistupovat až do proměnné $9. Pro hromadné zpracování se hodí příkaz shift, který z proměnné $1 udělá $0, z proměnné $2 udělá $1, atd.

Jak naplnit svou proměnnou

Operátorem = naplníte proměnnou. V případě, že pracujete s řetězcem, nezapomeňte ošetřit operátorové znaky.
a=42
nalada=vyborna
pocasi="oblacno, misty dest"
obed=houby\ s\ octem
V tomto příklad jsme naplnili proměnnou a hodnotou 42 (jestli je to číslo nebo řetězec je na tom, jak s ní budete zacházet), dále jsme naplnili proměnnou nalada hodnotou vyborna, proměnnou pocasi řetězcem oblacno, misty dest a proměnnou obed řetězcem houby s octem.

Volání proměnné

Hodnotu proměnné mohu volat tak, že před její název dám operátor $
echo $a
b=$a
Tisk proměnné pomocí příkazu echo nebo printf jste už mohli vidět, v druhém řádku příkladu uvádím, že proměnná b nechť je naplněna hodnotou proměnné a.

Načtení proměnné

Může se stát, že potřebujete naplnit proměnnou ze vstupu. Na to se hodí příkaz read
jana@perun:~$ read a
ahoj
jana@perun:~$ echo $a
ahoj
jana@perun:~$ 
Na druhém řádku je standardní vstup, do kterého jsem napsala "ahoj" a enter. Tím se naplnila proměnná a.
Příkaz read má mnoho užití, umí načítat proudy, soubory, má spoustu zajímavých parametrů a pro klidný večer doporučuji přečíst jeho manuálovou stránku, přinejmenším help read prolétněte zrakem.

Práce s řetězci

Nejprve si naplním dva řetězce, ať mám na čem ukazovat příklady:
abeceda=abcdefghijklmnopqrstuvwxyz
cisla=1234567890
Délka řetězce ${#retezec}
Úpravy proměnné budou v následujících příkazech vesměs takové, že uvedete operátor dolaru a do složených závorek specifikujete jakou proměnnou chcete jako zpracovat. Pro délku řetězce je to znak mřížky.
jana@drak:~$ echo ${#abeceda} ${#cisla}
26 10
Spojování řetězců $retezec1$retezec2
Spojování probíhá zcela bez nějakého operátoru
jana@drak:~$ echo $retezec1$retezec2
ahojnazdar
jana@drak:~$ echo $retezec1 $retezec2
ahoj nazdar
jana@drak:~$ echo $retezec1=$retezec2
ahoj=nazdar
Jediná zrada by mohla nastat, kdybyste chtěli řetězce proložit znaky jako zpětné lomítko nebo dolar, ale ty musíte tak jako tak ošetřit a nic to nemění na principu spojování řetězců.
Zkrácení řetězce $(retezec:o_kolik)
Práce s řetězci je poměrně snadná pokud ze všech shellů používáte zrovna bash. Zde příklady na zkrácení o kolik ze začátku a o kolik od kolikátého znaku.
jana@drak:~$ echo ${cisla:3}
4567890
jana@drak:~$ echo ${cisla:2:3}
345
jana@drak:~$ echo ${cisla:5:3}
678
Převedení na velká písmena${retezec^^}
Na podobnou operaci bývá zvykem volat příkaz sed, ale není to potřeba.
jana@drak:~$ abeceda=abcdefghijklmnopqrstuvwxyz
jana@drak:~$ echo ${abeceda^^}
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Převedení na malá písmena${retezec,,}
… a jde to pochopitelně i na druhou stranu.
jana@drak:~$ b=ABC
jana@drak:~$ echo ${b,,}
abc
Zaměnit řetězce${retezec/co_zmenit/na_co_zmenit}
Záměna části řetězce za jiný:
jana@drak:~$ echo ${abeceda/ab/AAAABBBB}
AAAABBBBcdefghijklmnopqrstuvwxyz
Tato záměna se provede pouze jednou v celém řetězci. Zde příklad, jak to mohu rozšířit.
jana@drak:~$ echo ${retezec/a/A}
Aaaaaaaa
jana@drak:~$ echo ${retezec//a/A}
AAAAAAAA
jana@drak:~$ echo ${retezec/%a/A}
aaaaaaaA
Pokud toužíte po ještě komplikovanějších výměnách, doporučuji studium regulárních výrazů a příkazu sed.

Počítání

Už bylo řečeno, že si nemusíte dělat hlavu s typy a počítat. To vám umožní rovnou několik příkazů.
Příkaz let
Pro takové drobné počítání ideální příkaz. Jen si dejte pozor, chce jen jeden argument, viz. příklad:
jana@drak:~$ x=5
jana@drak:~$ let y=$x+3
jana@drak:~$ echo $y
8
jana@drak:~$ let y = $x + 13
bash: let: =: syntax error: operand expected (error token is "=")
jana@drak:~$ let "y= $x + 13"
jana@drak:~$ echo $y
18
Násobení se provádí znakem hvězdička, který má ovšem operátorový význam a ten je mu potřeba vymluvit. Hvězdička uzavřená do uvozovek či ošetřená zpětným lomítkem funguje správně.
Aritmetická expanze
Pokud vám příkaz let nevyhovoval ze syntaktických důvodů, že požaduje pouze jeden parametr, u aritmetické expanze si stěžovat nebudete.
jana@drak:~$ x=5 ; y=$(($x + 3)); echo $y
8
jana@drak:~$ x=5 ; y=$(($x - 3)); echo $y
2
jana@drak:~$ x=5 ; y=$(($x * 3)); echo $y
15
jana@drak:~$ x=5 ; y=$(($x / 3)); echo $y
1
jana@drak:~$ x=5 ; y=$(($x % 3)); echo $y
2
jana@drak:~$ x=5 ; y=$((($x*2) - 3)); echo $y
7
Jednoduchou inkrementaci s aritmetickou expanzí zvládnete také:
jana@drak:~$ x=5 ; ((x++)) ; echo $x
6
Stejně jako u příkazu let nepotřebujete znak dolaru, protože do proměnné rovnou zapisujete.
Příkaz expr
Syntakticky krutý, ale funkčně výborný příkaz expr umožňuje aritmetiku, porovnávání, logické výrazy i práci s řetězci. Stačí, když si zapamatujete: narozdíl od let mu všechny parametry oddělte mezerami, nepoužívejte uvozovky a ošetřete hvězdičku, aby uměla násobit.
jana@drak:~$ expr 7 + 2
9
jana@drak:~$ expr 7 - 2
5
jana@drak:~$ expr 7 \* 2
14
jana@drak:~$ expr 7 / 2
3
jana@drak:~$ expr 7 % 2
1
jana@drak:~$ expr \( 7 / 2 \) \* 2
6
jana@drak:~$ x=5 ; y=$(expr $x + 1) ; echo $y
6

Co jsem neřekla a asi ani neřeknu

Třeba, že existují pole a jak se s nimi pracuje, spoustu triků v práci s řetězci, které bash umí úplně skvěle. Nebo, že jde počítat i v aritmetice s plovoucí čárkou. Na tomto místě se ve skriptech obvykle píše: Tuto látku ponechávám na laskavém čtenáři k dostudování. Až to bude potřebovat.