Yerel Kapsam ve Dönüş Kodlarıyla İşlev Tasarlama
Kırılgan genel değişkenler yerine yerel değişkenler, çıkış durumları ve printf tabanlı dönüş değerleri kullanan işlevler yazın.
Yerel Kapsam ve Dönüş Kodlarıyla İşlev Tasarlama, CoddyKit'te ücretsiz bir DevOps Bootcamp dersidir. Bu, 4 dersinin 1. 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, DevOps Bootcamp öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. DevOps Bootcamp kursu toplamda 4 dersten oluşur.
İşlev Kapsamı Neden Önemlidir?
Bash'te değişkenler varsayılan olarak geneldir. Bir işlevin içinde ayarlanan değişkeni açıkça local olarak bildirmediğiniz sürece bu değişken çağıranın kapsamına sızar. Bu, kabuk betiklerindeki ince hataların yaygın bir kaynağıdır.
localkullanılmayan işlevler, çağıranın değişkenlerinin üzerine sessizce yazabilir.localdeğişkenleri, işlev döndüğünde yok edilir.- Temiz kapsam sınırları, işlevleri yalıtılmış biçimde yeniden kullanılabilir ve sınanabilir hâle getirir.
Bu ders, kendi içinde bağımsız işlevler yazmayı öğretir: Bu işlevler local değişkenleri kullanır, sonuçları çıkış kodları ve printf aracılığıyla iletir ve örtük genel duruma asla güvenmez.
Global Değişken Sızıntısı Sorunu
Burada global bir değişken sızıntısına ilişkin somut bir örnek verilmiştir. set_name işlevi result adlı bir değişken tanımlar ve bu değişken, çağıranın kendi result değişkeninin üzerine sessizce yazılır.
Bu betiği çalıştırıp beklenmedik çıktıyı gözlemleyin — işlev çağrısından sonra çağıranın result değişkeni ortadan kaybolur.
#!/usr/bin/env bash
set_name() {
result="Alice" # No 'local' — this is GLOBAL
}
result="important data"
echo "Before: $result"
set_name
echo "After: $result" # Prints 'Alice', not 'important data''local' ile Yerel Değişken Tanımlama
local yerleşik komutu, bir değişkenin kapsamını onu çevreleyen işleve ve bu işlevin çağırdığı tüm işlevlere sınırlar. İşlevin dışında değişken ya tanımsız olur ya da önceki değerini korur.
local varname— değer atamadan tanımlar.local varname="value"— tek adımda tanımlar ve değer atar.local -i count=0— tamsayı türünde bir yerel değişken tanımlar.local -r PI=3.14159— salt okunur bir yerel sabit tanımlar.
En iyi uygulama: Global olması özellikle gerekmiyorsa, bir işlevin içindeki her değişkeni local olarak tanımlayın.
#!/usr/bin/env bash
greet() {
local name="$1" # local — safe
local greeting="Hello, ${name}!"
echo "$greeting"
} # 'name' and 'greeting' vanish here
name="global value"
greet "Bob"
echo "name is still: $name" # Prints 'global value'Dönüş Değerleri Olarak Çıkış Kodları
Bash işlevleri dizeleri return ile döndüremez — return yalnızca bir tamsayı çıkış durumu (0–255) belirler. Geleneksel olarak:
return 0— başarıreturn 1(veya sıfır olmayan herhangi bir değer) — başarısızlık
Çağıran, çağrıdan hemen sonra $? üzerinden çıkış durumunu okur veya işlevi doğrudan bir if koşulunda kullanır. Çıkış kodları, bir işlevden başarıyı veya başarısızlığı bildirmek için tercih edilen yöntemdir.
#!/usr/bin/env bash
is_even() {
local -i n="$1"
(( n % 2 == 0 )) # arithmetic command: exits 0 if true, 1 if false
}
for num in 2 3 7 10; do
if is_even "$num"; then
echo "$num is even"
else
echo "$num is odd"
fi
doneprintf ile Dize Sonuçlarını İletme
Bir işlevin dize sonucu döndürmesi gerektiğinde kullanılan standart yöntem, standart çıktıya yazdırmak ve sonucu komut ikamesi $() ile yakalamaktır. echo yerine printf kullanılması şu nedenlerle tercih edilir:
printf, siz eklemediğiniz sürece varsayılan olarak sona satır sonu eklemez (ancak\neklerseniz ekler).printfdavranışı tutarlıdır ve POSIX tarafından tanımlanmıştır;echokabuklar arasında farklılık gösterir.- Komut ikamesi sondaki satır sonlarını kaldırır; bu nedenle
printf '%s' "$value"kesin sonuç verir.
#!/usr/bin/env bash
to_uppercase() {
local input="$1"
printf '%s' "${input^^}" # Bash 4+ parameter expansion
}
word="hello"
upper=$(to_uppercase "$word")
echo "Original: $word"
echo "Upper: $upper"Çıkış Kodlarını ve Standart Çıktıyı Birleştirme
İyi tasarlanmış bir işlev aynı anda hem bir sonuç yazdırabilir (başarılı olduğunda) hem de başarısızlığı bildirebilir (çıkış kodu aracılığıyla). Çağıran, çıktıya güvenmeden önce çıkış koduna göre ne yapacağına karar verir.
Aşağıdaki yöntem gerçek Bash kitaplıklarında yaygın olarak kullanılır:
- Başarı durumunda: sonucu
printfile yazdırın vereturn 0kullanın. - Başarısızlık durumunda: tanı iletisini standart hataya (standart çıktıya değil) yazın ve
return 1kullanın. - Hataları standart hataya yazmak, standart çıktıyı ardışık işleme için temiz tutar.
#!/usr/bin/env bash
divide() {
local -i numerator="$1"
local -i denominator="$2"
if (( denominator == 0 )); then
printf 'Error: division by zero\n' >&2
return 1
fi
printf '%d' $(( numerator / denominator ))
return 0
}
if result=$(divide 20 4); then
echo "20 / 4 = $result"
else
echo "Division failed."
fi
if result=$(divide 10 0); then
echo "10 / 0 = $result"
else
echo "Division failed (caught the error)."
fi'local' Kullanarak Özyinelemeli İşlevleri Korumak
Özyineleme, local komutunun neden vazgeçilmez olduğunu en açık biçimde gösteren örneklerden biridir. Her özyinelemeli çağrı, çağrı yığınındaki her local değişkenin kendisine ait bağımsız bir kopyasını alır. local kullanılmazsa her çağrı aynı global değişkenin üzerine yazacak ve yanlış sonuçlar üretecektir.
Aşağıdaki faktöriyel işlevi güvenlidir; çünkü n ve sub her yığın çerçevesi için yereldir.
#!/usr/bin/env bash
factorial() {
local -i n="$1"
local -i sub
if (( n <= 1 )); then
printf '1'
return 0
fi
sub=$(factorial $(( n - 1 )))
printf '%d' $(( n * sub ))
}
for i in 1 2 3 4 5 6; do
echo "${i}! = $(factorial $i)"
donelocal -n (İsim Başvurusu) ile Alt Kabuk Tuzaklarından Kaçınma
Komut ikamesi $() bir alt kabukta çalışır. İçindeki değişken atamaları üst kabukta görünmez. Bir işlevin, alt kabuk kullanmadan çağıran tarafından sağlanan bir değişkene yazmasını istediğinizde Bash 4.3 ve sonraki sürümlerde kullanılabilen bir isim başvurusu (local -n) kullanın.
local -n ref="$1",refdeğişkenini$1içinde adı saklanan değişkenin takma adı yapar.- İşlev içinde
refdeğişkenine değer atamak, çağıranın değişkenini doğrudan değiştirir. - Bu yöntem, uygulama ayrıntılarını yerel tutarken alt kabuk kullanımını önler.
#!/usr/bin/env bash
# Fills caller's array by reference — no subshell needed
read_csv_line() {
local -n _out="$1" # nameref to caller's variable
local line="$2"
local IFS=','
read -ra _out <<< "$line"
}
declare -a fields
read_csv_line fields "alice,30,engineer"
echo "Name: ${fields[0]}"
echo "Age: ${fields[1]}"
echo "Role: ${fields[2]}"Küçük Bir İşlev Kitaplığı Oluşturma
Gerçek dünyadaki Bash projeleri, yeniden kullanılabilir işlevleri source ile (veya nokta işleci . ile) betiklere aktarılan kitaplık dosyalarına ayırır. İyi kitaplık tasarımı kuralları şunlardır:
- Bir kitaplık işlevinin içindeki her değişken
localolmalıdır. - Kitaplık işlevleri hiçbir zaman
exitkullanmaz — çağıranın çalışmaya devam edebilmesi içinreturnkullanırlar. - Ad çakışmalarını önlemek için tutarlı bir ad alanı ön eki kullanın (ör.
str_,log_). - Bir koruyucu değişken kullanarak dosyanın birden fazla kez aktarılmasını önleyin.
Aşağıda bu kuralları izleyen minimal bir dize yardımcı programı kitaplığı yer almaktadır.
#!/usr/bin/env bash
# lib/str.sh — string utility library
[[ -n "${_LIB_STR_LOADED:-}" ]] && return 0
_LIB_STR_LOADED=1
str_trim() {
local str="$1"
str="${str#"${str%%[![:space:]]*}"}"
str="${str%"${str##*[![:space:]]}"}"
printf '%s' "$str"
}
str_repeat() {
local -i times="$2"
local char="$1"
local -i i
for (( i = 0; i < times; i++ )); do
printf '%s' "$char"
done
}
str_contains() {
local haystack="$1"
local needle="$2"
[[ "$haystack" == *"$needle"* ]]
}
# --- self-test when executed directly ---
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
trimmed=$(str_trim " hello world ")
echo "Trimmed: '${trimmed}'"
str_repeat '-' 20; echo
if str_contains "bash scripting" "script"; then
echo "Contains: yes"
fi
fiİşlevlerin İçindeki Bağımsız Değişkenleri Doğrulama
Bağımsız değişken alan işlevler, bunları erkenden doğrulamalı ve geçersiz girdi durumunda belirli bir çıkış kodu döndürmelidir. Buna koruyucu koşul yöntemi denir — hızlı ve açık biçimde başarısız olun.
- Bağımsız değişken sayısını
$#ile denetleyin. - Herhangi bir işlem yapmadan önce türleri veya biçimleri doğrulayın.
- Tanı iletilerini yalnızca standart hataya yazdırın; standart çıktıya asla yazdırmayın.
- Farklı başarısızlık türlerine farklı tepki verebilmeleri için birbirinden farklı sıfır olmayan dönüş kodları kullanın (ör. 1 = yanlış bağımsız değişkenler, 2 = dosya bulunamadı).
#!/usr/bin/env bash
file_line_count() {
if (( $# != 1 )); then
printf 'Usage: file_line_count <file>\n' >&2
return 1
fi
local file="$1"
if [[ ! -f "$file" ]]; then
printf 'Error: not a file: %s\n' "$file" >&2
return 2
fi
if [[ ! -r "$file" ]]; then
printf 'Error: cannot read: %s\n' "$file" >&2
return 3
fi
local -i count
count=$(wc -l < "$file")
printf '%d' "$count"
return 0
}
# Test with /etc/hosts (exists on every Linux/macOS system)
if lines=$(file_line_count /etc/hosts); then
echo "/etc/hosts has $lines lines"
else
echo "Failed with exit code: $?"
fiHepsini Bir Araya Getirme: Gerçek Dünya Örneği
Bu dersteki tüm kavramların birlikte çalışmasını gösteren, eksiksiz ve kendi içinde bağımsız bir betik aşağıda verilmiştir:
- Her işlevde
localdeğişkenler. - Başarıyı veya başarısızlığı bildirmek için çıkış kodları.
- Dize sonuçlarını iletmek için
printf. - Standart hataya yazılan hatalar, standart çıktıya yazılan sonuçlar.
- Bağımsız değişken doğrulama için koruyucu koşullar.
Akışı inceleyin: parse_version verileri çıkarır, version_ge bunları karşılaştırır ve main her ikisini de düzenli biçimde kullanır.
#!/usr/bin/env bash
# Parse a semver string into components via nameref
parse_version() {
local -n _major="$2" _minor="$3" _patch="$4"
local version="$1"
local IFS='.'
local -a parts
read -ra parts <<< "$version"
_major="${parts[0]:-0}"
_minor="${parts[1]:-0}"
_patch="${parts[2]:-0}"
}
# Return 0 if version $1 >= version $2
version_ge() {
local -i maj_a min_a pat_a
local -i maj_b min_b pat_b
parse_version "$1" maj_a min_a pat_a
parse_version "$2" maj_b min_b pat_b
if (( maj_a != maj_b )); then (( maj_a > maj_b ))
elif (( min_a != min_b )); then (( min_a > min_b ))
else (( pat_a >= pat_b ))
fi
}
require_bash_version() {
local required="$1"
local actual="${BASH_VERSION%%(*}"
if version_ge "$actual" "$required"; then
printf 'Bash %s satisfies >= %s\n' "$actual" "$required"
return 0
else
printf 'Error: need Bash >= %s, got %s\n' "$required" "$actual" >&2
return 1
fi
}
main() {
require_bash_version "4.3" || return 1
require_bash_version "99.0" || true # demonstrates failure path
}
mainBilginizi Sınayın: Yerel Değişkenler ve Dönüş Değerleri
Aşağıdaki Bash işlevini inceleyin. Çağıran içinde dize sonucunu yakalamanın doğru yolu nedir ve tmp değişkeniyle ilgili hangi ifade doğrudur?
transform() {
local tmp="${1,,}" # lowercase
printf '%s' "$tmp"
return 0
}Özet: Yerel Kapsamlı ve Dönüş Kodlu İşlevler
Bu derste temiz, birleştirilebilir ve güvenli Bash işlevlerinin nasıl yazılacağını öğrendiniz:
- İşlevlerin içindeki değişkenler için her zaman
localkullanın; böylece çağıranın kapsamını kirletmezsiniz. - Başarıyı veya başarısızlığı bildirmek için çıkış kodlarını (
return 0/1/N) kullanın — bunlarif,&&ve||ile doğal biçimde bütünleşir. - Dize sonuçlarını iletmek için standart çıktıya
printfile yazın; çağıran içinde bunları$()ile yakalayın. - Hataları standart hataya (
>&2) yazın; böylece veri akışı ve ardışık işleme için standart çıktı temiz kalır. - Çağıranın sağladığı bir değişkene alt kabuk ek yükü olmadan yazmanız gerektiğinde
local -n(isim başvurusu) kullanın. - Koruyucu koşullar (bağımsız değişkenleri erkenden doğrulamak, geçersiz girdide hemen dönmek) işlevleri sağlam ve kendi kendini açıklayan hâle getirir.
- Kitaplık dosyaları aktarılmalı, ad alanı ön ekleri kullanmalı, hiçbir zaman
exitçağırmamalı ve birden fazla kez aktarılmaya karşı korunmalıdır.
Bu yöntemlerde ustalaşmak, kırılgan ve tek kullanımlık betiklerle profesyonel, sürdürülebilir Bash kod tabanları arasındaki farkı oluşturur.
Sıkça Sorulan Sorular
“Yerel Kapsam ve Dönüş Kodlarıyla İşlev Tasarlama” dersi ücretsiz mi?
Evet — “Yerel Kapsam ve Dönüş Kodlarıyla İşlev Tasarlama” 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 DevOps Bootcamp kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. DevOps Bootcamp kursu toplamda 4 dersten oluşur.
“Yerel Kapsam ve Dönüş Kodlarıyla İşlev Tasarlama” dersinde ne öğreneceğim?
Kırılgan genel değişkenler yerine yerel değişkenler, çıkış durumları ve printf tabanlı dönüş değerleri kullanan işlevler yazın. DevOps Bootcamp 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.
DevOps Bootcamp öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te DevOps Bootcamp, 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 1. dersidir.
“Yerel Kapsam ve Dönüş Kodlarıyla İşlev Tasarlama” 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 DevOps Bootcamp dersinde kod yazıp çalıştırabilir miyim?
Evet. Her DevOps Bootcamp 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
- Yerel Kapsam ve Dönüş Kodlarıyla İşlev Tasarlama
- Yeniden Kullanılabilir Bash Kitaplıkları Oluşturma ve Kaynak Alma
- getopts ile Bayrakları ve Bağımsız Değişkenleri Ayrıştırma
- Dizileri ve İlişkilendirilebilir Haritaları İşlevler Arasında Geçirme