Ayarlanmamış kullanma ve bir değişkeni boş olarak ayarlama


108

Şu anda, bir test fonksiyonunda hem standart bash testleri ( [[) hem de önceden tanımlanmış eşleştiricilerin kullanılabileceği bir bash test çerçevesi yazıyorum . Eşleştiriciler '[[' için sarmalayıcılardır ve bir dönüş kodu döndürmenin yanı sıra, bekleneni söyleyen anlamlı bir mesaj ayarlayın.

Misal:

string_equals() {
    if [[ ! $1 = $2 ]]; then
            error_message="Expected '$1' to be '$2'."

            return 1
    fi
}

Dolayısıyla, bir eşleştirici kullanıldığında ve başarısız olduğunda, ancak o zaman bir error_message ayarlanır.

Şimdi, bir noktada, testlerin başarılı olup olmadığını test ediyorum. Başarılı olursa, kırmızı renkte başarısız olursa beklentiyi yeşil olarak yazdırırım.

Ayrıca, bir error_message kümesi olabilir, bu yüzden bir mesajın var olup olmadığını test ederim, yazdırırım ve sonra onu kaldırırım (çünkü aşağıdaki test bir ayarlamayabilir error_message):

if [[ $error_message ]]; then
    printf '%s\n' "$error_message"

    unset -v error_message
fi

Şimdi sorum şu, değişkeni kaldırmak mı yoksa sadece '' olarak ayarlamak mı daha iyi?

error_message=''

Hangisi daha iyi? Gerçekten bir fark yaratıyor mu? Ya da belki mesajın ayarlandığını gösteren ek bir bayrağa sahip olmalı mıyım?


1
Asla error_messagebaşka bir şeyle karşılaştırmazsanız , önemli olmadığını söyleyebilirim. Bununla birlikte, istediğinizi düşünüyorum [[ $error_message ]], aksi takdirde "error_message" değişmez dizesinin var olup olmadığını test ediyorsunuz.
chepner

@chepner Evet, bir yazım hatasıydı. Onu düzeltti.
helpermethod

Yanıtlar:


143

Çoğunlukla, kullanmadığınız sürece bir fark görmezsiniz set -u:

/home/user1> var=""
/home/user1> echo $var

/home/user1> set -u
/home/user1> echo $var

/home/user1> unset var
/home/user1> echo $var
-bash: var: unbound variable

Yani gerçekten, değişkeni nasıl test edeceğinize bağlı.

Ayarlandıysa, tercih ettiğim test yöntemimin şudur:

[[ -n $var ]]  # True if the length of $var is non-zero

veya

[[ -z $var ]]  # True if zero length

43
var="ayarlanmadı" değil. Bu sadece alıntılanmamış boş bir dizedir. Buna ek olarak set -u, bash'ın çeşitli parametre genişletme biçimleri de set edilmemiş ve null değerleri ayırt edebilir: ${foo:bar}set edilmediğinde "bar" , null fooolduğunda "", foo unset veya null ise "bar" olarak genişler. foo${foo:-bar}
chepner

1
[[ -n $var ]]varboş dizeye ayarlanmışsa yanlıştır .
chepner

1
Değişken 'varlığını' kontrol etmek için 'declare -p' kullanırsanız, var = 'declare - var = ""' ifadesini gösterecektir, ondan kurtulmak için unset kullanmanız gerekir, elbette salt okunur bir değişken ise, elbette kurtulmak. Ayrıca, bir işlevin içinde var = bir şey kullanırsanız, "yerel var = değer" kullanırsanız, bundan kurtulma konusunda endişelenmenize gerek kalmayacak, ancak dikkatli olun, çünkü "declare var = değer" de yereldir. "declare -g var = değer" kullanarak bunu açıkça global olarak ayarlamanız gerekir, bunu açıkça "yerel" kullanarak yerel olarak ayarlamanız gerektiğini bildirmeden. Global değişkenler yalnızca silinir / ayarlanmamıştır.
osirisgothra

@osirisgothra: yerel değişkenler hakkında iyi bir nokta. Elbette genellikle en iyisi, bir fonksiyondaki tüm değişkenleri kapsüllenecek şekilde bildirmek (veya yerelleştirmek).
cdarke

3
@chepner ${foo-bar}yerine olmalıdır ${foo:bar}. kendin için test et:unset a; echo ">${a:-foo}-${a:foo}-${a-foo}<"
Liviu Chircu

17

Söylendiği gibi, unset kullanmak dizilerde de farklıdır.

$ foo=(4 5 6)

$ foo[2]=

$ echo ${#foo[*]}
3

$ unset foo[2]

$ echo ${#foo[*]}
2

2

Yani, dizi dizini 2'nin ayarını kaldırarak, aslında dizideki o öğeyi kaldırır ve dizi boyutunu (?) Azaltırsınız.

Kendi testimi yaptım ..

foo=(5 6 8)
echo ${#foo[*]}
unset foo
echo ${#foo[*]}

Sonuç ...

3
0

Yani, sırf tüm diziyi bozmanın aslında onu tamamen kaldıracağını açıklığa kavuşturmak için.


0

Yukarıdaki yorumlara dayanarak, işte basit bir test:

isunset() { [[ "${!1}" != 'x' ]] && [[ "${!1-x}" == 'x' ]] && echo 1; }
isset()   { [ -z "$(isunset "$1")" ] && echo 1; }

Misal:

$ unset foo; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's unset
$ foo=     ; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's set
$ foo=bar  ; [[ $(isunset foo) ]] && echo "It's unset" || echo "It's set"
It's set
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.