Bash dla Hobbystów. Zmienne

Na samym początku chciałbym zaznaczyć, że o ile będę starał się w miarę szczegółowo wyjaśniać poszczególne kwestie poruszane w dzisiejszym tekście, to zarówno dzisiaj jak i kolejnych odsłonach tego cyklu nie będę opowiadał o abecadle koderskim, na które składają się zmienne, pętle czy instrukcje warunkowe. Zakładamy po prostu, że czytelnik ma jakieś rozeznania w tym temacie, a w najgorszym wypadku będzie w stanie samodzielnie doczytać (tudzież “dozobaczyć”) czym są te konstrukcje programistyczne. Tym samy nie uświadczymy dzisiaj żadnych gawęd chociażby o pudełkach, które zawsze jak królik z kapelusza pojawiają się, gdy ktoś stara się wytłumaczyć laikom co to za dziwo ta “zmienna”. To powiedziawszy przejdźmy do rzeczy.

Komentarze

Ale wcześniej dwa słowa poświęcę komentarzom, tym bardziej, że jestem wielkim orędownikiem ich stosowania, zwłaszcza jeśli wiemy, że z naszego kodu mogą korzystać inne osoby.

Jeśli chodzi o basha, komentarze są poprzedzone znakiem #. Wszystko, co znajduje się w wierszu za tym symbolem, jest ignorowane przez powłokę. Nawet w przypadku wiersza shebang ( #!/bin/bash) mamy do czynienia – ze specjalnym wprawdzie – komentarzem, ponieważ jako taki nie jest on przez powłokę wykonywany. Ta ostatnia przetwarzając nasz skrypt odczytuje ten wiersz i stąd wie, którego interpretera poleceń użyć do wykonania zawartych tam instrukcji, ale wpływu na samo działanie programu nie ma to żadnego.

Jeśli chodzi o lokalizację komentarz może je rozpoczynać zarówno na początku linii (chyba najczęstsza praktyka), jak i w dowolnym innym miejscu wiersza. Niestety powłoka bash nie proponuje przy tym rozwiązania pozwalającego na tworzenie komentarzy wielowierszowych.

#!/bin/bash

# Autor: borciugner

# Data powstania: 2022-11-20

# Ten skrypt nie robi nic nadzwyczajnego i po prostu wita się ze światem.

 

echo “Hello world” #Użycie polecenia echo

 

exit 0

Zmiana – deklaracja oraz wywołanie

A teraz do sedna: zmienne w bash deklarowane są podobnie jak w Pythonie, czyli po prostu podajemy jakąś nazwę po czym następuje znak równości i po jego prawej stronie przypisujemy wartość, którą chcemy pod zmienną podstawić. Natomiast tutaj trzeba podkreślić wystąpienie pierwszego “dziwactwa” ze zmiennymi w bashy. Otóż między znakiem równości a nazwą zmiennej z jednej strony oraz przypisaną wartości z drugiej nie może być żadnych przerw (spacji). W przeciwnym razia interpreter “ucieszy” nasze oczy informacją o błędzie. Na pewnym poziomie abstrakcji wygląda to następująco:

nazwa_zmiennej=wartość zmiennej

zaś w praktyce – czyli w skrypcie – zobaczymy coś takiego na przykład:

autor=borciugner

Jak widać nie ma tutaj konieczności wskazywania wprost, że w tym miejscu odbywa się akt deklaracji zmiennej, choć nie jest prawdą, że w przypadku basha nie ma słowa kluczowego przewidzianego na tę okazję, który wskazywałby jednoznacznie oto jesteśmy świadkami powołania do życia zmienną (patrz niżej). Przyznam jednak, że ja sam nie używam takiej konstrukcji i chyba nie widziałem skryptu, którego autor miał taką potrzebę.

Wbrew obiegowej opinii o tym, że bash nie pozwala “po bożemu” deklarować zmiennych, jest w nim przewidziane słowo kluczowe, które na taką okoliczność można przywołać, a mianowicie declare.

Co ciekawe nie jest to tylko pusta konwencja wykreowana ze względu na programistycznych purystów, ponieważ przy pomocy tego słowa można przypisać do zmiennej typ liczbowy (integer). Wystarczy wówczas dodać do tego polecenia opcję -i. To pozwala na łatwiejsze wykonywanie działań arytmetycznych z czym bash generalnie ma pewien problem, o czym będzie mowa w kolejnym wpisie. 

Jeśli chodzi o reguły rządzące tworzeniem nazw zmiennych, to również w tym przypadku powłoka bash pozwala na dużą swobodę, bowiem do dyspozycji mamy wszystkie znaki alfanumeryczne oraz symbol podkreślenia czy tam – jak mawia mój syn – podłogi. Należy jednak pamiętać, że nazwa zmiennej nie możem zaczynać się od cyfry oraz – oczywiście jak to unixach bywa – wielkość liter ma znaczenie.

A jeśli już przy tej ostatniej kwestii jesteśmy, to wspomnę o pewnej konwencji, która jest chyba dość powszechnie stosowana, czyli praktyce zapisywania nazw zmiennych raczej małymi literami niż dużymi. To dobry nawyk ponieważ chroni nas przed pomieszaniem naszych zmiennych ze zmiennymi systemowymi w rodzaju tych, które zdążyliśmy już poznać (np. HOME, PATH, USER itp).

Wywołanie tak spreparowanej zmiennej wymaga następnie użycia symbolu $, który należy wstawić przed nazwą zmiennej, co zresztą widzieliśmy w poprzednim wpisie, gdy używaliśmy zmiennej PATH. Ot cała filozofia (no może nie do końca – patrz ramka).

Przeglądają skrypty różnych autorów nie raz ani dwa zobaczycie na przykład takich zapis przy próbie wywołania zmiennych:

${nazwa_zmiennej}

nawet jeśli z punktu widzenia logiki kodu nie ma to znaczenia (o czym zaraz). Wydaje mi się, że to całkiem niezłe podejście, choć sam w sobie nie wykształciłem takiego nawyku, zapewne dla tego, że niezwykle rzadko mam potrzebę do skorzystania z tej formy zapisu. By jednak zaprezentować, w jakich sytuacjach może to się okazać przydatne posłużmy się poniższym kodem:

#!/bin/bash

 

zmienna=“zmienna”

nowaZmienna=$zminnaNowa

kolejnaZmienna=${zmienna}Nowa

 

echo $zmienna

echo $nowaZmienna

echo $kolejnaZmienna

 

exit 0

W wyniku działania tego skryptu w oknie naszego terminala zobaczymy następujący rezultat (cyfry w nawiasach oznaczają numer wiersza):

(1) zmienna

(2)

(3) zmiennaNowa

Ten pusty wiersz wziął się z tego, że powłoka uznała, iż w przypadku deklaracji zmiennej nowaZmienna chcemy przypisać do niej wartość innej zmiennej, to jest tej o nazwie  zmiennaNowa, a ponieważ ta ostatnia nie istnieje, to wartością dla nowaZmienna jest pusty ciąg znaków. W przypadku kolejnaZmienna użycie nawiasów klamrowych pozwoliło na uzyskanie wartości będącą zbitką pierwszej zmiennej ze słowem “Nowa”.

Mi osobiście zdarzyła się tylko razy potrzeba skorzystania z nawiasów klamrowych, ale to były bardziej przypadki wykonywania pewnych “akademickich” ćwiczeń niż faktycznego zastosowania “w życiu”. Warto jednak o tym wiedzieć, by nie być w pewnym momencie niemiło zaskoczonym.

Koda, czyli finiszujemy

Do omówienia dzisiaj pozostała ostatnia kwestia,  a mianowicie  sposób przekazywania do zmiennej łańcuchów znaków składających się z kilku wyrazów albo inaczej rzecz ujmując: łańcucha znaków, który składa się między innymi ze spacji. W tym przypadku do dyspozycji mamy dwie metody, tj. z jednej strony zamknięcie ciągu znaków pomiędzy apostrofami, z drugiej zaś użycie do tego cudzysłowów. Osobiście w praktyce nie używam pierwszej z nich, ale gwoli kronikarskiej sumienności, napiszę, że ten sposób (apostrofy) pozwala nam przekazać interesujący nas ciąg do zmiennej lub innego polecenia w “oryginalnej” postaci, czyli bez żadnych modyfikacji ze strony interpretera. W przypadku cudzysłowów musimy być nieco ostrożniejsi, ponieważ “widząc” cudzysłów powłoka rości sobie prawo do pewnych specjalnych działań na tej treści. By to zobrazować użyjmy przykładu:

#!/bin/bash

 

imie=“Borciugner”

 

echo ‘Wołają na mnie $imie’

echo “Wołają na mnie $imie

 

exit 0

W efekcie w terminalu zobaczymy coś takiego:

Wołają na mnie $imie

Wołają na mnie Borciugner

Stało się tak dlatego, że w przypadku drugiego polecenia powłoka zinterpretowała (w tym przypadku prawidłowo, czyli zgodnie z naszymi intencjami) zapis $imie jako próbę wywołania takiej zmiennej. Jest to bardzo przydatna właściwość użycia cudzysłowów dlatego zalecam używania wyłącznie tej formy w celu wyrobienia w sobie odpowiedniego nawyku.

Ktoś się jednak zapyta, a co jeśli będziemy chcieli użyć znaku $ chociażby jako symbolu dolara, a przy tym umieścić to między cudzysłowami. Na tę okoliczność – podobnie jak w innych językach programowania – został pomyślany symbol ucieczki. W przypadku bash tę rolę spełnia tzw. odwrócony backslah (“\” – powinien się znajdować klawiszem “enter”). By się o tym przekonać wystarczy uruchomić taki prosty skrypcik:

#!/bin/bash

 

echo ‘Mam w kieszeni $100’

echo “Mam w kieszeni $100″

echo “Mam w kieszeni \$100″

 

exit 0

Decydując się na korzystanie z cudzysłowów należy również pamiętać, że w sytuacji, gdy chcemy “w treści” umieścić odwróconego backslasha – ot choćby w celu podania ścieżki do jakiegoś zasobu na Widowsach – trzeba postąpić analogicznie jak w przypadku znaku $, tj. przed nim użyć – a jakże -symbolu ucieczki. Czyli dostaniemy podwójny backslash w efekcie (patrz przykład niżej).

C:\\Windows\\Temp

Dwa słowa na zakończenie

Z przerażeniem stwierdzam, że wbrew pierwotnym założeniom teksty mojego autorstwa na temat skryptowania powłoki bash mają tendencje do nadmiernego rozrastania. Dlatego postanowiłem temat zmiennych podzielić na dwie części. W związku z tym dzisiejszy wpis dotyczył kwestii fundamentalnych dla tego zagadnienia, czyli głównie sposobu deklarowania zmiennych oraz podstawowych mechanizmów ich użycia. W kolejnym teście będę chciał poruszyć bardziej specyficzne dla bash zagadnienia w tym zakresie, czyli między innymi wykonywanie działań arytmetycznych oraz przekazywanie argumentów do skryptu. Będzie też bardzo krótko o tablicach oraz używania poleceń w zmiennych.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *