Ders 08 / 24
Özel Değişkenler ve Argümanlar
Konumsal parametreler, argüman listesinin iki gösterimi, listeyi tüketen döngü ve seçenek ayrıştırma.
Yayın Güncelleme
Bu derste
- Konumsal parametreleri ve betiğe ilişkin özel değişkenleri kullanır
- Argüman listesinin iki gösterimi arasındaki farkı boşluklu argümanla gösterir
- Kısa seçenekleri ayrıştıran ve hatalı kullanımı bildiren bir betik arayüzü kurar
İçindekiler
Kütük adı artık bir değişkenden geliyor, ama betiği çağıran için doğal yol bu değildir.
KUTUK=erisim.log ./rapor.sh yazmak yerine ./rapor.sh erisim.log yazmak beklenir.
Komut satırından gelen değerler, kabukta ayrı bir mekanizmayla — konumsal parametreler
(positional parameters) ile — karşılanır.
Programlama Temelleri kursunda fonksiyon parametreleri adlarıyla tanımlanıyordu. Kabukta adlandırma yoktur: parametreler numaralanır ve numaralarıyla okunur. Bu ders o numaraları, listeyi bir bütün olarak ele almanın iki yolunu ve seçenek ayrıştırmayı kurar.
Konumsal Parametreler
$1, $2, … betikçe alınan argümanları sırayla verir. $0 betiğin çağrıldığı adı,
$# argüman sayısını tutar.
#!/usr/bin/env bash # arg.sh echo "betik adi : $0" echo "arguman sayisi: $#" echo "ilk : $1" echo "ikinci : $2" echo "onuncu : ${10}"
chmod +x arg.sh ./arg.sh a b c d e f g h i j
betik adi : ./arg.sh arguman sayisi: 10 ilk : a ikinci : b onuncu : j
Dokuzdan büyük numaralar süslü ayraç ister. $10 yazılsaydı kabuk bunu $1 ve 0 diye
okur, ilk argümanın ardına sıfır ekleyerek a0 üretirdi. Ayraç kullanımı bu yüzden
zorunludur.
$0, betiğin çalıştırılırken yazıldığı addır; dosyanın gerçek adı olmak zorunda değildir
ve saltık yol içermeyebilir. Kullanım iletilerinde $0 yazmak yaygındır ama betiğin
adını sabit yazmak daha okunaklı bir çıktı verir.
Argüman Listesi: "$@" ve "$*"
Tüm argümanları birlikte aktarmak için iki gösterim vardır ve aralarındaki fark yalnızca tırnak içinde ortaya çıkar.
"$@", her argümanı ayrı bir kelime olarak genişletir."$*", tüm argümanlarıIFS’in ilk karakteriyle birleştirip tek kelime üretir.- Tırnaksız
$@ve$*, ikisi de kelime bölmeye uğrar ve ayrım kaybolur.
#!/usr/bin/env bash # liste.sh say() { printf 'sayi=%d\n' "$#"; printf ' <%s>\n' "$@"; } echo '--- "$@" ---'; say "$@" echo '--- "$*" ---'; say "$*" echo '--- $@ ---'; say $@
chmod +x liste.sh ./liste.sh "erisim kutugu.log" 404
--- "$@" --- sayi=2 <erisim kutugu.log> <404> --- "$*" --- sayi=1 <erisim kutugu.log 404> --- $@ --- sayi=3 <erisim> <kutugu.log> <404>
Üç sonuç üç farklı anlam taşır. İlki, çağıranın verdiği sınırları koruyarak listeyi aktarır. İkincisi listeyi tek metne çevirir — ileti yazdırmak dışında bir işe yaramaz. Üçüncüsü, boşluk içeren argümanı ikiye böler ve çağıranın niyetini bozar.
Kural: argümanları başka bir komuta aktarırken her zaman "$@" kullanın. Bu, önceki
dersteki tırnaklama kuralının konumsal parametrelere uzanmasıdır.
Listeyi Tüketmek
shift komutu konumsal parametreleri bir sola kaydırır: $2 yeni $1 olur, $# bir
azalır. Argümanları sırayla işleyen döngülerin temelidir.
#!/usr/bin/env bash # shift.sh while [ "$#" -gt 0 ]; do echo "islenen: $1 (kalan: $#)" shift done
chmod +x shift.sh ./shift.sh bir iki uc
islenen: bir (kalan: 3) islenen: iki (kalan: 2) islenen: uc (kalan: 1)
shift N biçimi bir defada N parametre atar. Kalan parametre sayısından fazlasını
atmaya çalışmak sıfırdan farklı kod döndürür ve listeyi değiştirmez.
Betiğe İlişkin Özel Değişkenler
Kabuk, çalışan betik hakkında birkaç değeri özel adlarda tutar.
| Ad | İçerik |
|---|---|
$? |
son komutun çıkış kodu |
$$ |
çalışan kabuğun süreç numarası |
$! |
arka planda başlatılan son sürecin numarası |
$- |
etkin kabuk seçenekleri |
$0 |
betiğin çağrıldığı ad |
$# |
konumsal parametre sayısı |
$$ geçici dosya adı üretmekte sık kullanılır; ancak süreç numaraları yeniden
kullanılabildiği için tek başına güvenli değildir. Tuzaklar ve Temizlik dersinde mktemp
ile doğru yol gösterilecek.
$! arka plan süreçlerini beklemek ve durdurmak için gerekir; Çıkış Kodları dersinde
sinyal kodları $$ ile üretilmişti.
Seçenek Ayrıştırma
Argümanları elle ayrıştırmak — birinci argüman seçenekse, ikinci onun değeriyse … —
kısa sürede okunmaz hâle gelir. getopts yerleşik komutu kısa seçenekleri sözleşmeye
uygun biçimde ayrıştırır.
getopts iki argüman alır: tanınan seçeneklerin dizgisi ve bulunan seçeneğin yazılacağı
değişken adı. Dizgideki bir harfin ardından : gelirse o seçenek değer bekler; değer
OPTARG değişkenine konur. Dizginin başındaki :, hata iletilerini getopts’un değil
betiğin üreteceğini bildirir.
#!/usr/bin/env bash # sec.sh adet=5 ayrinti=0 while getopts ':n:va' secenek; do case "$secenek" in n) adet="$OPTARG" ;; v) ayrinti=1 ;; a) echo "kullanim: sec.sh [-n SAYI] [-v] KUTUK"; exit 0 ;; :) echo "hata: -$OPTARG deger bekliyor" >&2; exit 2 ;; \?) echo "hata: bilinmeyen secenek -$OPTARG" >&2; exit 2 ;; esac done shift $((OPTIND - 1)) echo "adet=$adet ayrinti=$ayrinti kalan=$# ilk=[${1-yok}]"
Dört çağrı, dört davranışı gösterir:
chmod +x sec.sh ./sec.sh -n 3 -v erisim.log ./sec.sh erisim.log ./sec.sh -n ./sec.sh -z
adet=3 ayrinti=1 kalan=1 ilk=[erisim.log] adet=5 ayrinti=0 kalan=1 ilk=[erisim.log] hata: -n deger bekliyor hata: bilinmeyen secenek -z
Son iki çağrı 2 koduyla sonlandı. Kullanım hatasını başka bir hata sınıfından ayrı bir
kodla bildirmek, betiği zincirde kullanılabilir kılar.
OPTIND, getopts’un işlediği son argümanın sırasını tutar. Döngüden sonraki
shift $((OPTIND - 1)) satırı seçenekleri listeden atar; geriye yalnızca seçenek olmayan
argümanlar kalır. Bu satır unutulursa $1 hâlâ ilk seçeneği gösterir.
getopts yalnızca tek harfli seçenekleri tanır; --ayrinti gibi uzun seçenekler için
destek yoktur. Uzun seçenek gerekiyorsa while–case ile elle ayrıştırma yazılır. Ayrıca
case dallarındaki \? yazımındaki ters bölü gereklidir: ? case kalıplarında tek
karakter eşleyen özel bir simgedir.
Argüman Sonu İşareti
Tire ile başlayan bir değer, seçenek sanılabilir. Örneğin -eski.log adlı bir dosya,
çoğu komut tarafından seçenek olarak yorumlanır. Sözleşme, argüman listesinde --
görüldüğünde ondan sonrasının seçenek olmadığını kabul etmektir. Aşağıdaki kalıp tireyle
başlar ve kütükteki her satırda geçen - - [ dizisini arar; -- olmasa grep kalıbı
seçenek sanardı:
grep -c -- '- - \[' erisim.log
30
Kendi betiklerinizde de getopts bu işareti tanır ve orada durur. Değişkenden gelen
dosya adlarını başka bir komuta aktarırken -- yazmak, kullanıcı girdisiyle seçenek
karışmasını önler.
Betiğe Uygulama
rapor.sh artık bir arayüz kazanır: kaç satır listeleneceği -n ile, kütük adı ilk
konumsal parametreyle verilir.
#!/usr/bin/env bash # rapor.sh — erisim kutugunden ozet rapor uretir. # Kullanim: rapor.sh [-n SAYI] [KUTUK] adet=5 while getopts ':n:' secenek; do case "$secenek" in n) adet="$OPTARG" ;; :) echo "hata: -$OPTARG deger bekliyor" >&2; exit 2 ;; \?) echo "hata: bilinmeyen secenek -$OPTARG" >&2; exit 2 ;; esac done shift $((OPTIND - 1)) kutuk="${1:-erisim.log}" echo "== Kutuk: $kutuk (ilk $adet yol) ==" cut -d' ' -f7 "$kutuk" | sort | uniq -c | sort -rn | head -"$adet"
chmod +x rapor.sh ./rapor.sh -n 3
== Kutuk: erisim.log (ilk 3 yol) ==
6 /api/veri
4 /yok.html
4 /index.html
Betik hâlâ eksik: verilen kütük yoksa cut hata verir ve rapor başlığı boşuna basılmış
olur. Bu eksik sonraki dersin konusudur.
Özet
- Konumsal parametreler
$1’den başlar; dokuzdan büyük numaralar süslü ayraç ister.$#sayıyı,$0çağrılan adı verir. "$@"argümanları ayrı kelimeler olarak,"$*"tek kelime olarak genişletir; tırnaksız yazımda ikisi de kelime bölmeye uğrar. Aktarımda"$@"kullanılır.shiftlisteyi bir sola kaydırır ve argümanları sırayla tüketen döngüyü mümkün kılar.getoptskısa seçenekleri ayrıştırır;OPTARGdeğeri,OPTINDişlenen sırayı tutar ve döngüden sonrashift $((OPTIND - 1))gerekir.--işareti, ondan sonrasının seçenek olmadığını bildirir ve tire ile başlayan değerleri korur.
Sonraki Adım
Betik, kendisine verilen kütüğün var olduğunu ve okunabildiğini varsayıyor. Bu varsayımı
sınamak için bir koşul gerekir; kabukta koşul, bir komutun çıkış kodudur. Sonraki ders
dosya, dizgi ve sayı testlerini, [ ] ile [[ ]] arasındaki farkı ve bu farkın neden
sözdizim tercihi değil doğruluk meselesi olduğunu ele alır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.