Shell Script #8 – Değişkenlerle Oynamak

Değişkenlerle ilgili daha önce şöyle bir yazı yazmıştım. Gayet tabii, birkaç sayfayla anlatılabilecek bir konu değil.

Zaten bu yazıdan sonra da “Tamam, değişkenler bitti. Öğrendik.” diyemeyeceğiz. Emin olabilirsiniz.

Kod örneklerini GitHub reposunda bulabilirsiniz.

Bash ortamında substring örneği
Bash ortamında substring örneği

Değişken Değerlerine Erişmek

Aşağıdaki örneği defalarca yapmıştık öyle değil mi?:

[root@localhost ShellScripting101]# cat 12-degiskenlerle_oynamak.sh
#! /bin/bash

degisken=göz

printf "$degisken \n"


[root@localhost ShellScripting101]# ./12-degiskenlerle_oynamak.sh
göz

Bir değişken tanımladık ve değerine ulaştık. Fakat mevzu bununla kalmıyor. Şöyle bir kullanım şansımız da var:

[root@localhost ShellScripting101]# cat 12-degiskenlerle_oynamak.sh
#! /bin/bash

degisken=göz
printf "$degisken \n"


printf "$degisken $degiskenlük $degiskencü \n"

printf "$degisken ${degisken}lük ${degisken}cü \n"
[root@localhost ShellScripting101]# ./12-degiskenlerle_oynamak.sh
göz
göz ük ü
göz gözlük gözcü

Bu kullanım sayesinde, base bir değer üzerine yenilerini ekleyerek ilerleme şansımız oluyor. Daha işe yarar bir senaryo düşünelim. Yazılımınızın çalıştığı path “/opt/benim/yazilim/” olsun. Bu path’i bir değişken içine alıp, yukarıdaki syntax ile kullanarak içerideki farklı dizin ve dosyalara rahatlıkla erişebilirsiniz.

typeset Örnekleri

Değişkenlerimizin değer ve özelliklerini değiştirebileceğimiz bir bash internal var: typeset

[root@localhost ShellScripting101]# type typeset
typeset bir kabuk yerleşiğidir
[root@localhost ShellScripting101]# help typeset
typeset: typeset [-aAfFgilrtux] [-p] name[=value] ...
    Set variable values and attributes.

    Obsolete.  See `help declare'.

Yukarıdaki çıktıdan da anlaşılacağı üzere “obsolete” durumda. “Declare”e de değineceğiz. Ancak özellikle “aman elleme çalışıyor” denilen script’lerde karşınıza çıkma ihtimali var typeset’in.

Yaptığım denemelerde gördüğüm kadarıyla, typeset’i günümüzde kullanmak pek de sağlıklı görünmüyor. O yüzden birkaç basit örnekle geçiştiriyorum bu konuyu:

[root@localhost ShellScripting101]# cat 12-degiskenlerle_oynamak.sh
#! /bin/bash
#typeset

typeset -l kucuk

typeset -u buyuk

kucuk="BuyukHarflerYok"
buyuk="kUCUKharflerYOK"

echo $kucuk
echo $buyuk

typeset -i sayi
sayi=5
echo $sayi

typeset -i sayi2
sayi2=3,14
echo $sayi2

typeset -i sayi3
sayi3=yirmi8
echo $sayi3

[root@localhost ShellScripting101]# ./12-degiskenlerle_oynamak.sh
buyukharfleryok
KUCUKHARFLERYOK
5
14
0

Yukarıdaki örneklerde; “typeset -l“, değişkene değer atandığında tüm büyük harfleri küçük harfe çeviriyor. “typeset -u” ise bunun tam tersini yapıyor. “typeset -i“, bu değişkenin “integer” tipinde değer tutabileceğini gösteriyor. Çıktılara bakarsanız, değişkene ne değer verirsem vereyim, bir şekilde bir integer saklamayı hedefliyor.

declare Örnekleri

Yukarıda da belirttiğim gibi, obsolete olan typeset yerine declare kullanıyoruz. Declare’in de görevi aynı: Değişkenlerin değerleri ve özelliklerini yönetmek.

[root@localhost ShellScripting101]# help declare
declare: declare [-aAfFgilrtux] [-p] [name[=value] ...]
    Set variable values and attributes.

    Declare variables and give them attributes.  If no NAMEs are given,
    display the attributes and values of all variables.

    Options:
      -f        restrict action or display to function names and definitions
      -F        restrict display to function names only (plus line number and
        source file when debugging)
      -g        create global variables when used in a shell function; otherwise
        ignored
      -p        display the attributes and value of each NAME

    Options which set attributes:
      -a        to make NAMEs indexed arrays (if supported)
      -A        to make NAMEs associative arrays (if supported)
      -i        to make NAMEs have the `integer' attribute
      -l        to convert NAMEs to lower case on assignment
      -r        to make NAMEs readonly
      -t        to make NAMEs have the `trace' attribute
      -u        to convert NAMEs to upper case on assignment
      -x        to make NAMEs export

    Using `+' instead of `-' turns off the given attribute.

    Variables with the integer attribute have arithmetic evaluation (see
    the `let' command) performed when the variable is assigned a value.

    When used in a function, `declare' makes NAMEs local, as with the `local'
    command.  The `-g' option suppresses this behavior.

    Exit Status:
    Returns success unless an invalid option is supplied or an error occurs.

Aşağıdaki örneği inceleyelim:

[root@localhost ShellScripting101]# cat 12-degiskenlerle_oynamak.sh
#! /bin/bash

#declare

declare -i yenisayi
yenisayi=20
echo $yenisayi

yenisayi=20+5
echo $yenisayi

yenisayi=1+2+3+4+5
echo $yenisayi

yenisayi="ali"
echo $yenisayi

declare +i yenisayi
yenisayi="ali"
echo $yenisayi

declare -r saltokunur
saltokunur="test"
echo $saltokunur

declare -r ilkdeger="test"
echo $ilkdeger

[root@localhost ShellScripting101]# ./12-degiskenlerle_oynamak.sh
20
25
15
0
ali
./12-degiskenlerle_oynamak.sh: line 55: saltokunur: salt okunur değişken

test

declare -i” ile, tıpkı typeset’te olduu gibi, integer tipinde bir değişken tanımladık. Dikkatinizi çekmek istediğim bir satır var: “yenisayi=20+5“. Bu satırın sonucunda, değişkene değer olarak “25” atanıyor. Verilen “20+5” değeri, integer tipine cast ediliyor ve 25 değeri elde ediliyor. Bu değer de değişkene atanıyor. Aynı durum, “1+2+3+4+5” için de geçerli.

declare -r” ile, read-only (salt okunur) bir değişken tanımlıyoruz. “saltokunur” değişkeni, ilk değeri verilmeden tanımlanmış. Sonrasında bir değer atanıyor ve bu değer yazdırılmak isteniyor. Çıktıya baktığımızda ise “line 55“te hata görüyoruz. Read-only bir değişkene değer atamaya çalıştığımız için bu hatayı aldık. echo çıktısı ise boş satır yazdı, çünkü değişkenin bir değeri yok.

Bu durumdan kurtulmak için ise, read-only set edilen değişkenin declare sırasında değerini belirtmemiz gerekiyor. “declare -r ilkdeger=”test”” satırında olduğu gibi. Bu satırda; ilkdeger isimli, değeri test olan ve read-only bir değişken tanımlamış oluyoruz.

String Bölme İşlemleri

Bir string içinden belirli bir kısmı atmak ya da bir başka deyişle belirli bir kısmı almak için, “%” ve “#” karakterlerinden faydalanabiliriz.

Aşağıdaki örneği inceleyelim:

[root@localhost ShellScripting101]# cat 13-substring_ornekleri.sh
#! /bin/bash

#Substring örnekleri:

#Bir string içinden belirli kısımları alabilmek için bu yöntemlerden faydalanırız:

dosyayolu="/opt/remi/php74/root/usr/lib64/php/modules/"

#Değişkenin değerini yaz:
echo $dosyayolu

#En SAĞDAN başlayarak, /php ile başlayan İLK pattern'ı bul ve at:
printf "${dosyayolu%/php*} \n"
#/opt/remi/php74/root/usr/lib64/

#En SAĞDAN başlayarak, /php ile başlayan SON pattern'ı bul ve at:
printf "${dosyayolu%%/php*} \n"
#/opt/remi/

#Aşağıdaki örnekler de, yukarıdakilerle aynı mantıkta.
#Fakat "#" karakteri SOLDAN İLK pattern'ı alacak.
#"##" karakteri ise SOLDAN SON pattern'ı alacak.

#Dikkatinizi çekmek istediğim bir nokta daha var.
#"%" karakteri kullanırken, pattern'ı /php* şeklinde vermiştik.
#"#" karakteri kullanırken ise, pattern'ı */php şeklinde veriyoruz.

printf "${dosyayolu#*/php} \n"
#php/ ile başlayan ilk kısmı gördü ve kalanını attı
#74/root/usr/lib64/php/modules/


printf "${dosyayolu##*/php} \n"
#php/ ile başlayan son kısmı gördü ve kalanını attı
#/modules/
[root@localhost ShellScripting101]# ./13-substring_ornekleri.sh
/opt/remi/php74/root/usr/lib64/php/modules/
/opt/remi/php74/root/usr/lib64
/opt/remi
74/root/usr/lib64/php/modules/
/modules/

Örneğin ve içerisindeki yorumların yeterince açıklayıcı olduğunu düşünüyorum.

Constant Değerler

Script’lerinizde değişmesini hiç istemeyeceğiniz değerler olabilir. Bir IP adresi, port numarası, uzunbir komut dizisi gibi. Böyle durumlarda, değişkenlerinizi “readonly” hâle getirip constant‘lar (sabitler) oluşturabilirsiniz.

#!/bin/bash
#Constant tanımlama:
#Bir değişken oluşturalım ve ilk değerini verelim:
sabit="sabit değer"
echo $sabit
#Var olan bu değişkeni constant hâle getirelim:
readonly sabit
sabit="yeni değer"
#Hata verir

Çıktı ise şu şekilde görünecektir:

[root@localhost ShellScripting101]# ./12-degiskenlerle_oynamak.sh
sabit değer
./12-degiskenlerle_oynamak.sh: line 100: sabit: salt okunur değişken
[root@localhost ShellScripting101]#

Array Tanımlama

Bash script’lerinizde array kullanmak istiyorsanız, dikkat etmeniz gereken bazı noktalar var:

  • İndeksler sıfırdan başlar (E yani).
  • Array’ler string ve integer tipinde veri tutabilir.
  • Varsayılan olarak array elemanları string kabul edilir.
  • Atlanan indeksler yok sayılır.

String veriler tutan array örneği:

[root@localhost ShellScripting101]# cat 14-array_ornekleri.sh
#! /bin/bash

#Array tanımlama:
dizi[0]="Domates"
dizi[1]="Biber"
dizi[2]="Patlıcan"


#BU KULLANIM HATALI!
echo $dizi[1]
#Ekrana Domates[1] yazar.


#Dizinin bir elemanını yazdırmak için:
echo ${dizi[1]}

#Dizinin tüm elemanlarını yazdırmak için:
echo ${dizi[*]}


#Dizinin eleman sayısını yazdırmak için:
echo ${#dizi[*]}


#Dizilere değer verirken, index sırasını takip etmek zorunda değilsiniz.
#Atlanan değerler yok sayılacaktır:

dizi[26]="Roka"
dizi[38]="Nane"

#Roka yazar:
echo ${dizi[26]}
#Boş değer yazar:
echo ${dizi[27]}
#Eleman sayısını 5 gösterecek:
echo ${#dizi[*]}



[root@localhost ShellScripting101]# ./14-array_ornekleri.sh
Domates[1]
Biber
Domates Biber Patlıcan
3
Roka

5

Integer tipinde veri tutmak için ise “declare” kullanabiliriz.