Shell Script #2 – Değişkenler, Bazı Özel Karakterler ve Çıkış Kodları

Değişken Nedir?

Programlama ile ilgilendiyseniz hiç de yabancı olmayan bir kavramdır değişkenler (variables). Değişkenler için, bellek üzerinde saklanan bir verinin “etiketi” ya da “ismi” diyebiliriz. Bellekte belirli bir konumu ya da konumları çağırabilmek için değişkenlerden faydalanırız.

Bash Scripting Değişken Örnekleri

Bash ortamında değişkenlerin atanması ve değerlerinin çağrılmasında, farklı durumlar altında farklı kullanımlar ile karşılaşabilirsiniz. Bu bölümde genel kullanımda karşımıza çıkan şekillerinden bahsedeceğiz.

Değişkenler tanımlanırken ya da değerleri değiştirilirken isimleriyle çağrılır. Fakat değerleri getirilirken “$” ön ekini alırlar. Klasik bazı örnekler yapalım. Burayı numaralandırarak anlatacağım:

1. [root@localhost bashscript]# isim =Ali
2. -bash: isim: komut yok
3. [root@localhost bashscript]# isim=Ali
4. [root@localhost bashscript]# soyisim=Sezişli
5. [root@localhost bashscript]# mesaj=Merhaba $isim $soyisim
6. -bash: Ali: komut yok
7. [root@localhost bashscript]# mesaj="Merhaba $isim $soyisim"
8. [root@localhost bashscript]# echo mesaj
9. mesaj
10. [root@localhost bashscript]# echo $mesaj
11. Merhaba Ali Sezişli
12. [root@localhost bashscript]#
  1. isim” değişkenine “Ali” değerini vermeyi denedim.
  2. bash programı, “isim” isminde bir komut bulamadığını söyledi. Çünkü atama sırasında eşittirden önce bir boşluk bıraktım. Önemli not. Bash ortamında değişken atamaları yaparken boşluk bırakmamalısınız. Aksi takdirde bash, yazdığınız değerleri birbirinden ayrı komutlar ve o komutların argümanları olarak algılar.
  3. isim” değişkenine “Ali” değerini atadım.
  4. soyisim” değişkenine “Sezişli” değerini atadım.
  5. mesaj” değişkenine “Merhaba $isim $soyisim” değerini atamaya çalışıyorum. Dikkat edin, çift tırnak işaretleri yok. Aslında bash’e göre ben şunu yazdım: mesaj=Merhaba Ali Sezişli. “Eee ne var bunda?” diyebilirsiniz. Şöyle ki, yukarıda açıklamaya çalıştığım gibi, bash bu boşluklu kelimelerin her birini farklı birer komut gibi algılıyor.
  6. $isim değişkeninden gelen “Ali” değerini bir program gibi çalıştırmayı denedi. Başarısız oldu.
  7. Atama işlemini yaparken çift tırnak işaretleri arasına aldım ve bunların birer komut değil, metin (text) olduklarını ifade ettim.
  8. echo” programına “mesaj” yazmasını söyledim.
  9. Yazdı 🙂 “mesaj” kelimesini anlamış olması çok normal. Değişken olan mesaj’ı kast ettiğimi anlatmak için başına $ işareti koymalıydım.
  10. echo” programına “mesaj” değişkeninin değerini yazmasını söyledim.
  11. Beklediğimiz çıktıyı alabildik.
Bash scripting değişken ve değer örnekleri
Bash scripting değişken ve değer örnekleri

Hadi biraz çirkin işler yapalım:

1. [root@localhost bashscript]# test=42
2. [root@localhost bashscript]# echo test
3. test
4. [root@localhost bashscript]# echo $test
5. 42
6. [root@localhost bashscript]# test=A              L               İ
7. -bash: L: komut yok
8. [root@localhost bashscript]# test="A              L               İ"
9. [root@localhost bashscript]# echo $test
10. A L İ
11. [root@localhost bashscript]# echo "$test"
12. A              L               İ
13. [root@localhost bashscript]# echo '$test'
14. $test
15. [root@localhost bashscript]# degisken1=100 degisken2=200 degisken3=300
16. [root@localhost bashscript]# echo "$degisken1 $degisken2 $degisken3"
17. 100 200 300
18. [root@localhost bashscript]# echo $degisken1 $degisken2 $degisken3
19. 100 200 300
20. [root@localhost bashscript]#
  1. “test” değişkenine 42 değerini atıyorum.
  2. Ekrana “test” yazdırıyorum. Değişken olan test değil. $ işareti kullanmamışım.
  3. Beklendiği gibi “test” yazıldı.
  4. Bu sefer test değişkenini yazdırmak istiyorum. Başında $ işareti var.
  5. Beklendiği gibi 42 yazıldı.
  6. test” değişkenine yeni değerler atamak istiyorum. Fakat aralarda boşluk karakterleri var. Atama işlemlerinde buna izin verilmiyor.
  7. Bash atama işlemini yapacakken, boşluktan sonra gelen karakterleri komut sanıyor. “L” komutunu çalıştırmak istiyor ve başarılı olamıyor.
  8. test” değişkenine çift tırnak işaretleri içerisinde, boşluklar kullanarak değer atıyorum.
  9. test” değişkenini yazdırmak istiyorum.
  10. Ekrana yalnızca birer boşluk bırakılmış şekilde “A”, “L” ve “İ” harfleri geliyor.
  11. Aynı değişkeni çift tırnak işaretleri içerisinde yazdırmayı deniyorum.
  12. Tıpkı tanımladığım zamanda olduğu gibi, birden fazla boşlukla ekrana basılıyor.
  13. test” değişkenini tek tırnak işaretleri arasında yazdırmayı deniyorum.
  14. echo” programı, tek tırnak arasında “string literal” beklediğinden; ekrana olduğu gibi “$test” karakterlerini yazıyor.
  15. Bu satırda, aralarında yalnızca birer boşluk bırakarak 3 farklı değişken tanımlayıp değer ataması yapıyorum. Bu kullanım çok tavsiye edilmiyor. Gerek kod okunurluğu gerekse script’in taşınabilirliği açısından sıkıntılı bir kullanım.
  16. 3 değişkenin değerini de yazdırmak istiyorum. Çift tırnak işaretlerini kullanıyorum.
  17. Beklendiği gibi “100 200 300” çıktısını görüyorum.
  18. 3 değişkenin değerini, çift tırnak işaretleri olmadan “echo“ya gönderiyorum.
  19. Beklendiği gibi “100 200 300” çıktısını görüyorum.

Bazı Özel Karakterler

Önceki yazılarımızda bazılarına değinmiştik. Burada ve ilerleyen örneklerde karşımıza farklı özel karakterler çıkacak.

Bash ortamına aşinaysanız; çift tırnak (“), tek tırnak (‘), pipe (|), soru işareti (?), yıldız (*), ampersand (&), noktalı virgül (;) gibi karakterlerin nerede, ne zaman, ne amaçla kullanıldığını zaten biliyorsunuzdur. Tek tek tüm karakterleri inceleyip açıklamam mümkün değil. Zaten böyle bir bilgim de yok. Karşımıza çıktıkça anlamlandırmaya çalışacağız bu karakterleri.

Aşağıda yer alan tablo, bu karakterlerin genel kullanım amacını göstermektedir. Fakat karakterler farklı noktalarda farklı şekilde davranabilir. İlk yazıdaki çift tırnak örneğini hatırlayın.

KarakterÖzellik
*0, 1 ya da daha fazla karakter için wildcard
?1 karakter için wildcard
;Tek satırda uç uca farklı komutları bağlar
|Kendinden önceki çıktıyı, kendinden sonraki programa gönderir
&İşlemi arkaplanda başlatır
||OR işleci
&&AND işleci
#!Shebang (yalnızca en üstte yer alırsa)
#Yorum satırı
$Değişkenleri ifade eder
$(…)Parantezler içindeki komutu çalıştır ve çıktısını gönderir
Bash scripting’te kullanılan bazı özel karakterler

Tekrar, üzerine basa basa vurgulamak isterim, bu karakterler her seferinde yukarıda yazıldığı gibi çalışmak zorunda değil. Farklı özel anlarda farklı görevleri olabilir.

Bir Bash Script Örneği

Basit bir script hazırlamaya çalışalım. Bu script’ten beklediklerimiz şunlar olacak:

  1. Kullanıcıya “adıyla” hitap etsin.
  2. Bugünün tarihini yazsın.
  3. Sistemde oturum açmış aktif kullanıcı sayısını göstersin.
  4. Ekrana bir takvim bassın.
  5. 0 koduyla çıksın.

Çevre Değişkenleri

GNU/Linux sistemlerde çevre değişkenleri (environment variables, env), uygulamaların kullanımı için bazı değerler saklarlar. Örneğin bir text dosyası açacaksınız. Peki varsayılan text editörünüz nedir? Şu an sistemde hangi kullanıcı bu uygulamayı kullanıyor? Hangi dizindeyiz? Arayüzümüz hangi dilde? Bu ve buna benzer genel değerler haricinde, kendiniz de çevre değişkenleri tanımlayıp bunları kullanabilirsiniz.

Yazının konusu çevre değişkenleri olmadığı için hiç irdelemiyorum bu konuyu. Fakat yine de içime sinmedi. “env” programına bir bakın derim.

Çıkış Kodları

GNU/Linux ortamında çıkış kodlarını inceleyerek yazılımların davranışlarını görebilirsiniz. Çoğu zaman, eğer bir yazılım doğru çalıştıysa, çıkış kodu olarak 0 (sıfır) görürsünüz. Fakat şunu unutmayın, çıkış kodlarını belirleyen kişi yazılımcıdır. Aşağıda “ls” programının farklı çıkış kodlarını görebilirsiniz. Son komutunuzun çıkış kodunu görmek için “echo $?” komutunu kullanabilirsiniz. Bu kodlara “exit code” ya da “return code” da denilebilir.

[ali@localhost bashscript]$ ls /root
ls: dizin /root açılamadı: Erişim engellendi
[ali@localhost bashscript]$ echo $?
2
[ali@localhost bashscript]$ ls /home/ali
hello.c  hello.exe
[ali@localhost bashscript]$ echo $?
0
[ali@localhost bashscript]$ ls -abcdfefgerert
ls: geçersiz seçenek -- e
Try 'ls --help' for more information.
[ali@localhost bashscript]$ echo $?
2

Yukarıda göreceğiniz üzere “ls” programı başarılı çalıştığında 0 kodunu döndürdü. Fakat erişim engellendiğinde ya da yanlış bir argüman verildiğinde 2 koduyla çıktı.

Şimdi şu çıktıyı inceleyelim:

[ali@localhost ~]$ gcc -o hello.exe hello.c
[ali@localhost ~]$ echo $?
0
[ali@localhost ~]$ ./hello.exe
Hello World!
[ali@localhost ~]$ echo $?
123
[ali@localhost ~]$

gcc” yardımıyla bir C kodu derlenmiş. 0 koduyla çıkmış. “hello.exe” adında bir program oluşturulmuş. Bu program, ekrana “Hello World!” yazıp alt satıra geçmiş ve görevini tamamlamış. Fakat döndürdüğü kod “123“. Neden? Başarıyla çalışmadığı için mi? Hayır. Yazılımcı öyle istediği için.

#include <stdio.h>

int main()
{
      printf("Hello World!\n");
      return 123;
}

Yukarıdaki “return” kelimesinden sonra gelen “123” değeri, bu program başarılı çalıştığında dönecek değeri gösteriyor. C dersi alan arkadaşlarım. “Hocam neden hep return 0 yazıyoruz?” diye sorduğunuzda (umarım sormuşsunuzdur); “Ya işte o genelde öyle yazılıyor.” ya da “Yok canım ben öyle yazıyorum sen istersen başka bir şey yazabilirsin.” şeklinde yanıtlardan ötesini alamamış olabilirsiniz. Belki de yazılımcılar bir zamanlar, “Arkadaşlar çok kasmayalım başarılı olursa sıfır döndürelim tamam mı?” diye anlaşmıştır kendi aralarında 🙂

Script’in Hazırlanması

Bu bölümdeki kodların başına, açıklamaları kolaylaştırması için satır numaraları ekleyeceğim.

1. #! /bin/bash

2. echo "Merhaba $USER"
3. echo "Bugün: $(date)"
4. echo -e "Aktif kullanıcı sayısı: \c"; who | wc -l
5. echo "Takvimin:"
6. cal

7. exit 0

Hadi inceleyelim:

  1. Shebang satırı. Bu script’in “/bin/bash” programı aracılığıyla yorumlanmasını istiyorum.
  2. Ekrana “Merhaba” kelimesinin yanında bir de çevre değişkenlerinden “$USER” değişkeninin yazdırılmasını istedim. “$USER”, şu an çalışan oturumun sahibini gösterir.
  3. date” programını çalıştırıp, çıktısını bir basamak dışarıda olan “echo” programına gönderiyorum. Bu konuyu debugging yaparken incelemiştik.
  4. Burası biraz farklı. “echo” programının “man” sayfasına bakarsanız; “\c” ifadesinin “Çıktı vermeyi bırak.” gibi bir anlamı olduğunu görürsünüz. Fakat echo, sizin gerçekten “\c” yazıp yazmak istemediğinizi nereden bilebilir? Bu yüzden echo’nun “-e” flag’ini kullanırız. Böylece echo, göreceği backslash‘li ifadelere farklı davranması gerektiğini anlar. Peki neden böyle bir şey yapıyorum? Neden çıktı vermeyi bırakmasını istiyorum? Çünkü echo, karakteristik olarak bir şey yazdıktan sonra alt satıra geçer. Fakat ben bunu istemiyorum. Onun yerine sistemdeki aktif oturumların sayısını görmek istiyorum. Burada “echo” tarafı ile sayıyı hesaplayan tarafı “;” karakteriyle birbirine bağladık. echo bir şeyler yazdı. Alt satıra geçemeden durduruldu. Noktalı virgül gelince bash şunu anladı: “Bu satırda buraya kadar olan yeri zaten çalıştırdım. Ama devamında başka bir şeyler de var.”. “who” programı sistemdeki açık oturumları listeler. Bu çıktıyı görmek yerine pipe ile (|) “wc” (word count) programına gönderdim. “wc” programı, kendine verilen verinin kaç satır, kaç kelime ve kaç byte olduğunu gösterir. Ben sadece satır sayısını bilmek istediğim için “-l” flag’ini kullandım.
  5. Ekrana “Takvimin:” yazdık.
  6. cal” programını çalıştırdık. “cal” programı, shell’inizde bir takvim gösterir.
  7. 0 koduyla script’i sonlandırdık.

Çalıştıralım:

[root@localhost bashscript]# ./egzersiz_1.sh
Merhaba root
Bugün: Cum Kas 20 14:08:22 +03 2020
Aktif kullanıcı sayısı: 1
Takvimin:
     Kasım 2020
Pz Sa Çr Pr Cu Ct Pa
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
[root@localhost bashscript]# echo $?
0
[root@localhost bashscript]#

Ekranda görülen çıktıları, yukarıdaki kod açıklamalarıyla eşleştirmeye çalışırsanız anlaşılır hâle gelecektir diye düşünüyorum.

Aslında yukarıdaki komutları tek tek yazsanız da benzer sonuçlar alacaksınız:

[root@localhost bashscript]# echo "Merhaba $USER"
Merhaba root
[root@localhost bashscript]# echo "Bugün: $(date)"
Bugün: Cum Kas 20 14:10:52 +03 2020
[root@localhost bashscript]# echo -e "Aktif kullanıcı sayısı: \c"; who | wc -l
Aktif kullanıcı sayısı: 1
[root@localhost bashscript]# echo "Takvimin:"
Takvimin:
[root@localhost bashscript]# cal
     Kasım 2020
Pz Sa Çr Pr Cu Ct Pa
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
[root@localhost bashscript]#

Bash script’in olayı aslında bu. “Sen yapsan zaten yaparsın. Fakat bırak bilgisayar yapsın o işi.” dediğimiz anlarda yardımımıza koşuyor. Tekrarlı işler, uzun komutlar, birbirini takip etmesi gereken işler gibi durumlarda hazırlanacak bir bash script, çalıştırdıktan sonra bilgisayarınızı kendi hâline bırakabileceğiniz şekilde işlerinizi sizin yerinize yapmaya devam edebilir.

Sonuç Olarak

Bash script’ler sayesinde shell’inizde yaptığınız işleri otomatize edebilirsiniz.

Bash script’ing yaparken, aslında kabuğu kullanmaya devam ediyorsunuz. Kabukta kullandığınız özel karakterler ve komutlar, script’lerde de kullanılabiliyor. Tabii ki bazı özel senaryolarda işler beklendiği gibi gitmeyebilir.

Değişken atamalarında boşluk karakterine dikkat edin. Değişken değerlerini kullanırken yalın, tek tırnaklı ve çift tırnaklı kullanımların farkını bilin.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir