0Pricing
Linux Command Line & Bash Scripting Mastery · Ders

Dizileri ve İlişkilendirilebilir Haritaları İşlevler Arasında Geçirme

Karmaşık veri yapılarını güvenle işlevlere aktarmak ve işlevlerden almak için ad başvurularını ve dolaylı genişletmeyi kullanın.

Dizileri ve İlişkilendirilebilir Haritaları İşlevler Arasında Geçirme, CoddyKit'te ücretsiz bir Linux Command Line & Bash Scripting Mastery dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Linux Command Line & Bash Scripting Mastery öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Linux Command Line & Bash Scripting Mastery kursu toplamda 4 dersten oluşur.

Dizileri İşlevlere Aktarmak Neden Zordur

Bash'te diziler ve ilişkisel diziler birinci sınıf değerler değildir. Bir diziyi işleve aktarmaya çalıştığınızda yalnızca $my_array kullanamazsınız; bu ifade sadece ilk öğeyi genişletir.

Şu hatalı denemeyi inceleyiniz:

my_func "${my_array[@]}"

İşlev, sözcüklerden oluşan düz bir liste alır. Bir öğenin nerede bitip diğerinin nerede başladığını bilemez ve dizi yapısını tamamen kaybeder.

Bash, karmaşık veri yapılarını aktarmak için iki güvenilir mekanizma sağlar:

  • İsim referansları (declare -n) — ada göre başka bir değişkene başvuru (Bash 4.3+)
  • Dolaylı genişletme (${!varname[@]}) — adı başka bir değişkende saklanan bir değişkene erişim (daha eski Bash sürümleri)

Bu derste her iki tekniği de ele alarak diziler ve eşlemelerle çalışan sağlam, yeniden kullanılabilir işlevler yazabilmeniz sağlanacaktır.

İsim Referansı Kullanarak Bir Diziyi Adıyla Aktarma

Günümüzdeki en temiz yaklaşım isim referansıdır: dizinin adını bir dize olarak aktarırsınız ve işlevin içinde ona başvuran yerel bir değişken tanımlarsınız.

Temel söz dizimi:

  • declare -n ref="$1" — ref, artık ilk bağımsız değişken olarak aktarılan değişken adının takma adıdır
  • ref değişkenini, özgün diziymiş gibi okuyabilir, üzerinde yineleme yapabilir ve değiştirebilirsiniz

Bu yaklaşım dizinin tamamının kopyalanmasını önler ve işlevin her boyuttaki dizilerle çalışmasını sağlar.

#!/usr/bin/env bash

print_array() {
    declare -n arr="$1"   # nameref: arr -> caller's variable
    echo "Array has ${#arr[@]} elements:"
    for elem in "${arr[@]}"; do
        echo "  - $elem"
    done
}

fruits=(apple banana cherry)
print_array fruits

Bir Çağıranın Dizisini İşlev İçinde Değiştirme

İsim referansı gerçek bir takma ad olduğundan, isim referansı üzerinden yapılan yazma işlemleri çağıranın özgün değişkenini değiştirir. Değerleri geri yazdırmanız veya genel değişkenler kullanmanız gerekmez.

Bu nedenle isim referansları, dizileri yerinde dönüştüren işlevler için idealdir; örneğin dizeleri normalleştirmek, öğeleri filtrelemek veya sıralamak için kullanılabilir.

#!/usr/bin/env bash

to_uppercase() {
    declare -n _arr="$1"
    for i in "${!_arr[@]}"; do
        _arr[$i]="${_arr[$i]^^}"   # ^^ = uppercase in Bash 4+
    done
}

words=(hello world bash)
echo "Before: ${words[@]}"
to_uppercase words
echo "After:  ${words[@]}"

İsim Referansı Üzerinden Yeni Bir Dizi Döndürme

Bir işlev, adını çıktı parametresi olarak kabul ederek çağıranın sağladığı bir diziye yazabilir. Çağıran boş bir dizi oluşturur, adını aktarır ve işlev bu diziyi doldurur.

Bu yöntem, sonuç arabelleğine işaretçi aktarmaya dayanan klasik C deyimini andırır; ancak burada işlem tamamen kabuk içinde gerçekleştirilir.

#!/usr/bin/env bash

get_even_numbers() {
    local -a source=("$@")
    # Last argument is the output array name — pop it off
    local out_name="${source[-1]}"
    unset 'source[-1]'

    declare -n _out="$out_name"
    _out=()   # clear
    for n in "${source[@]}"; do
        (( n % 2 == 0 )) && _out+=("$n")
    done
}

declare -a evens
get_even_numbers 1 2 3 4 5 6 7 8 evens
echo "Evens: ${evens[@]}"

İsim Referansı Çakışması Tuzağı

İsim referanslarıyla ilgili kritik bir sorun vardır: yerel isim referansı değişkeni çağıranın değişkeniyle aynı adı taşıyorsa Bash sonsuz bir öz-referans döngüsüne girer ve betik başarısız olur.

Örneğin çağıran dizisine arr adını vermiş ve işlev declare -n arr="$1" çalıştırmışsa, arr isim referansı kendisini gösterir.

Bunu önlemek için kural: dahili isim referansı değişkenlerinin başına alt çizgi koyunuz (ör. _arr, _ref, _out). Çağıranlar bu tür adları neredeyse hiç kullanmadığından çakışmalar son derece nadir olur.

#!/usr/bin/env bash

# DANGER: caller uses variable named 'arr'
arr=(one two three)

bad_func() {
    declare -n arr="$1"   # collision! arr refers to itself
    echo "${arr[@]}"
}

good_func() {
    declare -n _arr="$1"  # underscore prefix avoids collision
    echo "${_arr[@]}"
}

# bad_func arr   # would hang / error
good_func arr

İlişkisel Dizileri (Eşlemeleri) Adıyla Aktarma

İlişkisel diziler (declare -A) isim referanslarıyla aynı şekilde çalışır. Eşlemenin adını bir dize olarak aktarır ve işlevin içinde bir isim referansı tanımlarsınız; böylece tüm anahtar-değer çiftlerine tam okuma ve yazma erişimi elde edersiniz.

Bu özellik, kitaplık işlevleri arasında paylaşılması gereken yapılandırma eşlemeleri, seçenek çözümleyicileri ve arama tabloları için son derece değerlidir.

#!/usr/bin/env bash

print_map() {
    declare -n _map="$1"
    echo "Map contents:"
    for key in "${!_map[@]}"; do
        printf '  %-15s => %s\n' "$key" "${_map[$key]}"
    done
}

declare -A config
config[host]="localhost"
config[port]="5432"
config[db]="myapp"

print_map config

İsim Referansıyla İki Eşlemeyi Birleştirme

İsim referansları işleve canlı bir takma ad sağladığından, eşleme birleştirme gibi yardımcı programları temiz bir şekilde uygulayabilirsiniz. Hedef eşlemeyi ve bir veya daha fazla kaynak eşlemeyi adlarıyla aktarın; işlev, kaynak anahtarları üzerinde yineler ve bunları hedefe yazar.

İsim referansları, betiğinizdeki her türlü ilişkisel diziyle çalışan tek bir genel merge_map işlevi yazmayı mümkün kılar.

#!/usr/bin/env bash

merge_map() {
    # merge_map dest src
    declare -n _dest="$1"
    declare -n _src="$2"
    for key in "${!_src[@]}"; do
        _dest["$key"]="${_src[$key]}"
    done
}

declare -A defaults=([timeout]=30 [retries]=3 [verbose]=false)
declare -A overrides=([retries]=5 [log_level]=debug)

merge_map defaults overrides

for k in "${!defaults[@]}"; do
    echo "$k = ${defaults[$k]}"
done

Dolaylı Genişletme: Daha Eski Bash Sürümleriyle Uyumluluk

Bash 4.0–4.2 sürümlerini (veya daha eski macOS varsayılan kabuklarını) desteklemeniz gerekiyorsa declare -n kullanılamaz. Alternatif, ${!varname} ile dolaylı genişletme kullanmaktır.

Dolaylı genişletme, varname değerini bir değişken adı olarak değerlendirir ve o değişkenin değerini döndürür. Diziler için tüm öğeleri almak üzere bunu özel bir söz dizimiyle birleştirirsiniz.

İsim referanslarına göre sınırlamalar:

  • Uygulamada yalnızca okunabilirdir (geri yazmak eval gerektirir; bu da kod ekleme riskleri taşır)
  • İlişkisel dizi anahtarları eval olmadan güvenli bir şekilde yinelenemez
  • Mümkün olan her yerde isim referanslarını kullanın; dolaylı genişletmeye yalnızca gerektiğinde başvurun
#!/usr/bin/env bash

sum_array() {
    local arr_name="$1"
    # Indirect: build a temporary copy by expanding arr_name[@]
    local -a items
    eval "items=( \"\${${arr_name}[@]}\" )"
    local total=0
    for n in "${items[@]}"; do
        (( total += n ))
    done
    echo "$total"
}

numbers=(10 20 30 40)
result=$(sum_array numbers)
echo "Sum: $result"

Modüler Bir Betik Kitaplığı Oluşturma

Profesyonel Bash projelerinde yardımcı işlevler kitaplık dosyalarında (ör. lib/array_utils.sh) saklanır ve bunlara ihtiyaç duyan betikler tarafından kaynak olarak yüklenir.

Yöntem şöyledir:

  • Her kitaplık dosyası yalnızca işlev tanımlar; üst düzey yan etkiler içermez
  • Bir nöbetçi değişken kullanarak dosyanın iki kez kaynak olarak yüklenmesini önleyin: [[ -n $__LIB_LOADED ]] && return; __LIB_LOADED=1
  • Tüketici betikleri kitaplığı yüklemek için source veya . kullanır
  • İşlevler karmaşık verileri isim referanslarıyla paylaşarak tüm mantığı kendi içinde tutar

Böylece tek kullanımlık kabuk çözümleri yerine sınanabilir, yeniden kullanılabilir ve bakımı kolay betikler elde edilir.

Uygulamalı Örnek: Eşleme Döndüren Seçenek Çözümleyici

Gerçek dünyadan bir kullanım örneği: çağıranın sağladığı ilişkisel diziyi dolduran bir komut satırı seçenek çözümleyicisi. Çağıran, dizi adını ilk bağımsız değişken olarak, ardından gerçek "$@" bağımsız değişkenlerini aktarır.

Bu yöntem, herhangi bir betiğin aynı çözümleyiciyi kodu kopyalamadan veya genel değişkenlere güvenmeden yeniden kullanmasını sağlar.

#!/usr/bin/env bash

parse_opts() {
    declare -n _opts="$1"
    shift
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --host)   _opts[host]="$2";   shift 2 ;;
            --port)   _opts[port]="$2";   shift 2 ;;
            --user)   _opts[user]="$2";   shift 2 ;;
            *)        echo "Unknown option: $1" >&2; shift ;;
        esac
    done
}

declare -A opts=([host]=localhost [port]=5432 [user]=admin)
parse_opts opts --host db.example.com --port 3306

echo "Connecting to ${opts[host]}:${opts[port]} as ${opts[user]}"

Tek İşlevde Girdi ve Çıktı İsim Referanslarını Birleştirme

İşlevler aynı anda birden fazla isim referansı barındırabilir; biri girdi, diğeri çıktı için kullanılabilir. Bu, saf dönüştürme işlevlerini mümkün kılar: işlevler bir kaynak yapıyı okur, bir sonuç hesaplar ve genel duruma dokunmadan bunu bir hedef yapıya yazar.

Her isim referansı için farklı, başına alt çizgi konmuş adlar kullanmak, çağıranın değişkenleri basit adlara sahip olsa bile çakışmaları olanaksız kılar.

#!/usr/bin/env bash

filter_map_by_key_prefix() {
    # Usage: filter_map_by_key_prefix src_map dest_map prefix
    declare -n _src="$1"
    declare -n _dst="$2"
    local prefix="$3"

    _dst=()
    for key in "${!_src[@]}"; do
        if [[ $key == ${prefix}* ]]; then
            _dst["$key"]="${_src[$key]}"
        fi
    done
}

declare -A settings=(
    [db_host]=localhost [db_port]=5432
    [cache_ttl]=300     [cache_driver]=redis
    [app_debug]=true
)
declare -A db_settings

filter_map_by_key_prefix settings db_settings db_

for k in "${!db_settings[@]}"; do
    echo "$k = ${db_settings[$k]}"
done

Bilgi Kontrolü: İsim Referansları ve Dizi Aktarımı

Bash'te dizileri ve eşlemeleri işlevler arasında aktarma konusundaki anlayışınızı sınayın.

Özet: Bash'te Karmaşık Veri Yapılarını Aktarma

Bu derste öğrendikleriniz:

  • Diziler değer olarak aktarılamaz; bunun yerine değişkenin adını bir dize olarak aktarın.
  • declare -n ref="$varname" bir isim referansı oluşturur: çağıranın değişkenine yönelik canlı bir takma addır. Hem okumalar hem de yazmalar özgün değişkene uygulanır. Bash 4.3+ gerektirir.
  • İsim referansı çakışması, dahili ve harici değişken aynı adı taşıdığında oluşur. Dahili isim referanslarının başına _arr, _map gibi bir alt çizgi koyarak bunu önleyin.
  • Çıktı parametreleri, boş bir sonuç dizisinin veya eşlemesinin adını aktararak çalışır; işlev bunu bir isim referansı üzerinden doldurur.
  • Tek bir işlevde kullanılan birden fazla isim referansı, genel yan etkiler olmadan saf girdiden çıktıya dönüşümleri mümkün kılar.
  • Dolaylı genişletme (${!varname[@]} + eval), Bash < 4.3 için daha eski bir geri dönüş yöntemidir; ancak kod ekleme riskleri taşır ve uygulamada yalnızca okunabilirdir.
  • Modüler, yeniden kullanılabilir ve sınanabilir Bash kod tabanları oluşturmak için bu teknikleri kaynak olarak yüklenen kitaplık dosyalarıyla birleştirin.

Sıkça Sorulan Sorular

“Dizileri ve İlişkilendirilebilir Haritaları İşlevler Arasında Geçirme” dersi ücretsiz mi?

Evet — “Dizileri ve İlişkilendirilebilir Haritaları İşlevler Arasında Geçirme” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Linux Command Line & Bash Scripting Mastery kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Linux Command Line & Bash Scripting Mastery kursu toplamda 4 dersten oluşur.

“Dizileri ve İlişkilendirilebilir Haritaları İşlevler Arasında Geçirme” dersinde ne öğreneceğim?

Karmaşık veri yapılarını güvenle işlevlere aktarmak ve işlevlerden almak için ad başvurularını ve dolaylı genişletmeyi kullanın. Linux Command Line & Bash Scripting Mastery ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

Linux Command Line & Bash Scripting Mastery öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Linux Command Line & Bash Scripting Mastery, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.

“Dizileri ve İlişkilendirilebilir Haritaları İşlevler Arasında Geçirme” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu Linux Command Line & Bash Scripting Mastery dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Linux Command Line & Bash Scripting Mastery dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Yerel Kapsam ve Dönüş Kodlarıyla İşlev Tasarlama
  2. Yeniden Kullanılabilir Bash Kitaplıkları Oluşturma ve Kaynak Alma
  3. getopts ile Bayrakları ve Bağımsız Değişkenleri Ayrıştırma
  4. Dizileri ve İlişkilendirilebilir Haritaları İşlevler Arasında Geçirme
← Linux Command Line & Bash Scripting Mastery Sayfasına Dön