Yürütme exit
bir kabuktaki bir tuzak olduğunu:
#!/bin/bash
function calc { echo 42; exit 1; }
echo $(calc)
Komut dosyası 42 yazdırır, alt kabuktan dönüş koduyla çıkar 1
ve komut dosyasıyla devam eder. echo $(CALC) || exit 1
Geri dönüş kodu, geri dönüş kodundan echo
bağımsız olarak 0 olduğundan , aramanın değiştirilmesi bile yardımcı olmaz calc
. Ve calc
önce idam edilir echo
.
Daha da şaşırtıcı olanı , aşağıdaki senaryoda olduğu gibi yerleşik yapıya exit
sarılarak etkisini engelliyor local
. Bir giriş değerini doğrulamak için bir fonksiyon yazdığımda problemin üstesinden geldim. Örnek:
20141211.log
Bugün "year month day.log" adlı bir dosya oluşturmak istiyorum . Tarih, makul bir değer sağlayamayan bir kullanıcı tarafından girilir. Bu nedenle, benim fonksiyonumda kullanıcı girişinin geçerliliğini doğrulamak için fname
dönüş değerini kontrol ediyorum date
:
#!/bin/bash
doit ()
{
local FNAME=$(fname "$1") || exit 1
touch "${FNAME}"
}
fname ()
{
date +"%Y%m%d.log" -d"$1" 2>/dev/null
if [ "$?" != 0 ] ; then
echo "fname reports \"Illegal Date\"" >&2
exit 1
fi
}
doit "$1"
İyi görünüyor. Komut dosyasını adlandırın s.sh
. Kullanıcı betiği ile çağırırsa ./s.sh "Thu Dec 11 20:45:49 CET 2014"
, dosya 20141211.log
oluşturulur. Bununla birlikte, kullanıcı yazarsa ./s.sh "Thu hec 11 20:45:49 CET 2014"
, komut dosyası çıktısını alır:
fname reports "Illegal Date"
touch: cannot touch ‘’: No such file or directory
Satır fname…
, alt kabukta hatalı giriş verilerinin tespit edildiğini söylüyor. Fakat çizginin exit 1
sonunda local …
asla tetiklenmez, çünkü local
direktif daima geri döner 0
. Bunun nedeni local
, daha sonra çalıştırılmasının $(fname)
ve dönüş kodunun üzerine yazmasının nedenidir. Ve bu nedenle, komut dosyası devam eder ve touch
boş bir parametre ile çağırır . Bu örnek basittir ancak bash'ın davranışı gerçek bir uygulamada oldukça kafa karıştırıcı olabilir. Biliyorum, gerçek programcılar locals kullanmıyor.
local
Açıklığa kavuşturmak için: Komut dosyası olmadan geçersiz bir tarih girildiğinde komut dosyası beklendiği gibi iptal edilir.
Düzeltme çizgiyi gibi bölmektir
local FNAME
FNAME=$(fname "$1") || exit 1
Garip davranış, bash'ın local
man sayfasındaki belgelere uyuyor : "Bir fonksiyon dışında yerel kullanılmadığı, geçersiz bir ad sağlandığı veya isim salt okunur bir değişken olmadığı sürece dönüş durumu 0'dır."
Hata olmamasına rağmen, bash'ın davranışının tersine dönük olduğunu hissediyorum. İnfazın sırasının farkındayım local
, yine de kesilmiş bir ödevi maskelememeliyim.
İlk cevabım bazı yanlışlıklar içeriyordu. Mikeserv ile yapılan açıklayıcı ve derinlemesine bir tartışmadan sonra (bunun için teşekkür ederim) Onları tamir etmeye gittim.