Bash Dizileri Üzerinde Temel İşlemler: Uzunluk, Arama, Dilimleme ve Ters Çevirme

Bash dizilerinin uzunluğunu alma, içerisinde değer arama, dilimleme ve ters çevirme işlemlerini adım adım öğrenin. Pratik komutlar ve örneklerle desteklenmiş rehber.

L
Linuxize
5 görüntülenme
Bash Dizileri Üzerinde Temel İşlemler: Uzunluk, Arama, Dilimleme ve Ters Çevirme

Giriş

Bash betiklerinde dizilerle çalışmak, özellikle de dizilerin uzunluğunu bulma, içerisinde değer arama, dilimleme veya elemanların sırasını değiştirme gibi işlemler yaparken bazen karmaşık görünebilir. Bash, bu işlemleri desteklemesine rağmen, genişletme (expansion) sözdizimini akılda tutmak zor olabilir.

Bu rehberde, Bash betiklerinde en sık kullanılan dizinli (indexed) diziler üzerinde yapılan temel işlemler detaylı olarak ele alınacaktır. Dizilerin tanımlanması, elemanlara erişim ve ilişkisel diziler hakkında daha fazla bilgi için Bash dizileri rehberine başvurabilirsiniz.

Örnek Dizi

Örneklerde aşağıdaki dizi kullanılacaktır:

fruits=( "apple" "banana" "dragon fruit" "date" "elderberry" )

Her bir tırnak içindeki değer bir eleman olarak kabul edilir ve dizinler 0'dan 4'e kadar devam eder.

Dizi Uzunluğunu Alma

Toplam Eleman Sayısını Bulma

Dizinin toplam eleman sayısını almak için ${#name[@]} genişletmesini kullanabilirsiniz:

echo "${#fruits[@]}"

Bu komut, dizideki beş eleman nedeniyle 5 çıktısını verecektir. Alternatif olarak ${#name[*]} kullanımı da aynı sonucu verir, ancak @ işaretçisi, diğer dizin işlemlerinde (örneğin dilimleme) bireysel elemanları koruduğu için daha güvenlidir.

Not: @ ve * arasındaki fark, @ genişletmesinin tırnak içinde kullanıldığında her bir elemanı ayrı bir kelime olarak korumasıdır. Bu, özellikle boşluk içeren elemanlarla çalışırken önemlidir.

Tek Bir Elemanın Karakter Uzunluğunu Bulma

Belirli bir dizin konumundaki elemanın karakter uzunluğunu bulmak için, o elemanın dizinini de ekleyin:

echo "${#fruits[1]}"

Bu komut, banana kelimesinin altı karakterden oluştuğunu gösterecektir.

Dizi İçinde Değer Arama

Değerin Dizide Bulunup Bulunmadığını Kontrol Etme

Bash, dizilerde değer arama için yerleşik bir contains operatörüne sahip değildir. Güvenilir bir yaklaşım, diziyi döngüye alarak her bir elemanı hedef değerle karşılaştırmaktır:

contains() {
  local target=$1
  shift
  
  local element
  for element in "$@"; do
    if [[ $element == "$target" ]]; then
      return 0
    fi
  done
  
  return 1
}

if contains "dragon fruit" "${fruits[@]}"; then
  echo "found"
else
  echo "not found"
fi

Bu fonksiyon, hedef değer bulunduğunda 0, bulunmadığında ise 1 durum kodunu döndürür. "${fruits[@]}" kullanımı, boşluk içeren değerleri korur.

Uyarı: Diziyi tek bir string haline getirip düzenli ifadelerle arama yapmak gibi kolay yollardan kaçının. Bu yaklaşım, arama teriminin başka bir elemanın içinde yer alması veya elemanların ayırıcı karakterler içermesi durumunda yanlış eşleşmelere neden olabilir.

Dizi Dilimleme

Diziyi Dilimleme

Dizi dilimleme için aşağıdaki genişletme kullanılır:

${name[@]:offset:length}

offset, dilimin başladığı konumu seçer ve length, döndürülecek eleman sayısını belirtir. Örneğin, dizinden 1. dizinden başlayarak üç eleman almak için:

slice=( "${fruits[@]:1:3}" )
printf '<%s>
' "${slice[@]}"

Bu komut, banana, dragon fruit ve date elemanlarını yeni bir dizi halinde döndürecektir.

Negatif Offset ile Dilimleme

Negatif bir offset kullanarak dizinin sonundan başlayabilirsiniz. Negatif sayıdan önce bir boşluk bırakarak Bash'in :- operatörünü varsayılan değer operatörü olarak algılamasını önleyin:

last_two=( "${fruits[@]: -2}" )
printf '<%s>
' "${last_two[@]}"

Bu komut, dizinin son iki elemanını (date ve elderberry) döndürecektir.

Not: length parametresini belirtmediğinizde, offset konumundan dizinin sonuna kadar olan tüm elemanlar alınır.

Diziyi Ters Çevirme

Diziyi Ters Sıraya Çevirme

Bash, dizileri ters çevirmek için yerleşik bir operatöre sahip değildir. Aşağıdaki döngü, dizinin dizinlerini sondan başa doğru okuyarak her bir değeri yeni bir diziye ekler:

indices=( "${!fruits[@]}" )
reversed=()

for ((i=${#indices[@]}-1; i>=0; i--)); do
  reversed+=( "${fruits[${indices[i]}]}" )
done

printf '<%s>
' "${reversed[@]}"

Bu işlem, diziyi ters çevirerek elderberry, date, dragon fruit, banana ve apple sırasını oluşturacaktır.

Not: Bu yöntem, hem sürekli dizilerde hem de dizinler arasında boşluklar bulunan seyrek dizilerde de çalışır.

Başka Araçlar: rev ve tac gibi araçlar farklı problemleri çözmek için kullanılır. rev, her giriş satırındaki karakterleri ters çevirirken, tac satır sırasını ters çevirir. Bu araçlar doğrudan Bash dizileri üzerinde çalışmaz.

Dizi Üzerinde Döngü İşlemleri

Sadece Değerler Üzerinde Döngü Yapma

Sadece dizinin değerleri üzerinde döngü yapmak için "${name[@]}" genişletmesini kullanın:

for fruit in "${fruits[@]}"; do
  echo "$fruit"
done

Tırnak içindeki genişletme, dragon fruit gibi boşluk içeren değerlerin tek bir döngü öğesi olarak kalmasını sağlar.

Hem Dizin Hem De Değer Üzerinde Döngü Yapma

Hem dizin hem de değer üzerinde döngü yapmak için ${!name[@]} kullanarak dizin listesini genişletin:

for i in "${!fruits[@]}"; do
  echo "$i: ${fruits[i]}"
done

Bu işlem, her bir dizin ve karşılık gelen değeri ekrana yazdırır.

Diziye Eleman Ekleme ve Önüne Ekleme

Dizinin Sonuna Eleman Ekleme

Dizinin sonuna bir veya daha fazla eleman eklemek için += operatörünü kullanın:

fruits+=( "fig" "grape" )

Yeni değerler, dizinin sonuna eklenir ve mevcut dizinlerin devamı olarak yeni dizinler alır.

Dizinin Başına Eleman Ekleme

Dizinin başına bir eleman eklemek için, yeni elemanı önce ekleyerek diziyi yeniden oluşturun:

fruits=( "apricot" "${fruits[@]}" )

Bu atama, diziyi 0'dan başlayan sürekli dizinlerle yeniden oluşturur.

Belirli Bir Dizin Konumuna Değer Atama

Belirli bir dizin konumuna değer atamak için aşağıdaki sözdizimini kullanın:

fruits[10]="kiwi"

Bu işlem, dizinler 7 ila 9 arasında boşluk bırakarak seyrek bir dizi oluşturur.

Dizi Elemanlarını Kaldırma

Belirli Bir Dizin Konumundaki Elemanı Kaldırma

Belirli bir dizin konumundaki elemanı kaldırmak için unset komutunu kullanın:

unset 'fruits[2]'

Argümanı tırnak içine alarak köşeli parantezlerin dosya adı kalıbı olarak algılanmasını önleyin. Kaldırılan dizin konumunda boşluk oluşur ve kalan elemanlar orijinal dizinlerini korur.

Diziyi Yeniden İndeksleme

Diziyi sürekli dizinlere sahip olacak şekilde yeniden oluşturmak için dizinin mevcut değerlerini kendisine atayın:

fruits=( "${fruits[@]}" )

Bu işlem, değerleri korur ve dizinleri 0'dan yeniden numaralandırır.

Tüm Diziyi Kaldırma

Tüm diziyi kaldırmak için sadece dizinin adını kullanın:

unset fruits

Hızlı Referans

Görev Sözdizimi
Eleman sayısı ${#arr[@]}
Tek bir elemanın uzunluğu ${#arr[index]}
Tüm değerler "${arr[@]}"
Tüm dizinler "${!arr[@]}"
Dilim "${arr[@]:offset:length}"
Son iki eleman "${arr[@]: -2}"
Eleman ekleme arr+=(x y)
Başa eleman ekleme arr=(x "${arr[@]}")
Belirli bir dizine değer atama arr[index]=value
Tek bir elemanı kaldırma unset 'arr[index]'
Kaldırmadan sonra yeniden indeksleme arr=("${arr[@]}")
Tüm diziyi kaldırma unset arr

Yaygın Hatalar ve Çözümleri

  1. Dizilere Erişimde Süslü Parantezleri Kullanmama:

    $fruits[1] komutu, $fruits değişkenini genişletir ve ardından [1] metnini ekrana yazdırır. Doğru kullanım ${fruits[1]} olmalıdır.

  2. Dizi Genişletmelerini Tırnak İçinde Kullanırken Dikkat Etmeme:

    "${fruits[@]}" kullanımı, her bir elemanı ayrı bir kelime olarak genişletirken, "${fruits[*]}" tüm elemanları IFS değişkeninin ilk karakteriyle birleştirir. Döngüler ve fonksiyonlarda @ formunu kullanın.

  3. Dizinlerin Sürekli Olduğunu Varsayma:

    unset kullanımı veya uzak bir dizine değer atanması sonrasında dizinlerin sürekli olduğunu varsaymayın. Gerçek dizin değerleri önem taşıyorsa "${!fruits[@]}" üzerinden döngü yapın.

  4. Negatif Offset Kullanırken Boşluk Bırakmama:

    Negatif offset kullanırken : - operatörünü varsayılan değer operatörü olarak algılanmasını önlemek için boşluk bırakın. Örneğin: ${arr[@]: -2}.

Sonuç

Bash dizilerinin uzunluklarını bulma, dilimleme, ters çevirme ve diğer temel işlemleri, genişletme mekanizmalarıyla kolayca yapılabilir. Dizi elemanlarının sınırlarını korumak için tırnak içindeki @ genişletmelerini kullanın ve dizinler arasında boşluklar olabileceğini unutmayın. Bu rehberde verilen örnekler ve açıklamalar, Bash betiklerinde dizilerle çalışırken karşılaşabileceğiniz yaygın durumlar için temel bir referans oluşturacaktır.

Kaynak

Linuxize