Bir bash değişkeninin boş olup olmadığı nasıl belirlenir?


Yanıtlar:


1053

Bir değişken atanmamışsa veya boş dizgeye ("") ayarlanmışsa bu, true değerini döndürür.

if [ -z "$VAR" ];

14
Bu, bir değişkenin "" değerine ayarlanmış olup olmadığını içerir mi?
Brent,

11
Evet öyle ... "-z" sıfır uzunluklu bir dizge için test eder.
David Z

91
if [ ! -z "$VAR" ];
Aaron Copley,

263
tersi -zolan-n if [ -n "$VAR" ];
Felipe Alvarez

19
Çift tırnak, değişkenin bölünmemesini sağlar. Bir $varkomut satırındaki basit bir boşlukla beyaz bir parametre listesine bölünürken "$var", her zaman yalnızca bir parametre olacaktır. Değişkenleri alıntılamak çoğu zaman iyi bir uygulamadır ve beyaz boşluk içeren dosya adlarını açmanızı engeller (diğer şeylerin yanı sıra). Örnek: Yaptıktan sonra a="x --help", deneyin cat $a- size yardım sayfasını verecektir cat. Sonra deneyin cat "$a"- (genellikle) söyler cat: x --help: No such file or directory. Kısacası, erken teklif ve sık sık teklif ve neredeyse hiç pişman olmayacaksınız.
Score_Under

247

Bash'te, desteklemeyen mermilerin taşınabilirliği ile ilgilenmiyorsanız, her zaman çift köşeli sözdizimini kullanmalısınız:

Aşağıdakilerden herhangi biri:

if [[ -z $variable ]]
if [[ -z "$variable" ]]
if [[ ! $variable ]]
if [[ ! "$variable" ]]

Bash'te, çift köşeli ayraçlar kullanıldığında, alıntılar gerekli değildir. Bir değişken için testi kolaylaştırabilirsiniz yapar bir değer için içerir:

if [[ $variable ]]

Bu sözdizimi ksh ile uyumludur (en azından ksh93, yine de). Saf POSIX veya sh veya dash gibi daha eski Bourne mermilerinde çalışmaz.

Çift ve tek köşeli parantezler arasındaki farklar hakkında daha fazla bilgi için buradaki cevabımı ve BashFAQ / 031'e bakınız .

Bir değişkenin özel olarak belirsiz olup olmadığını test edebilirsiniz (boş bir dizgeden farklı olarak):

if [[ -z ${variable+x} ]]

burada "x" isteğe bağlı.

Bir değişkenin null olup olmadığını bilmek istiyorsanız, kümelenmemiş:

if [[ -z $variable && ${variable+x} ]]

1
Bu if [[ $variable ]]benim için iyi çalıştı ve set -uönerilen diğer çözümlerden birinin gerektirdiği şeye bile ihtiyaç duymuyordu .
Teemu Leisti 14:12

3
Bunun kabul edilen cevaptan daha iyi olduğunu düşünüyorum.
qed

2
Bunu yaparken neden taşınabilir olmayan bir özellik önerirsiniz?
Alastair Irvine

19
@AlastairIrvine: Cevabımın ilk cümlesindeki taşınabilirlikten bahsediyorum, soru başlığı ve gövdesi "Bash" kelimesini içeriyor ve soru bash olarak etiketlendi ve çift dirsek yapısı birçok yönden açık avantajlar sağlıyor . Ve tutarlılık ve bakım kolaylığı için karıştırma braketi stillerini önermiyorum. Maksimum, en düşük ortak payda taşınabilirliğine ihtiyacınız varsa sh, Bash yerine kullanın . Sağladığı yeteneklerin arttırılması gerekiyorsa, Bash'i kullan ve tamamen kullan.
Dennis Williamson

2
@BrunoBronosky: Düzenlemeyi geri aldım. İçin bir gereksinim yoktur ;sonunda. thenHiç bir noktalı virgül olmadan sonraki satırda olabilir.
Dennis Williamson

230

Bash'deki bir değişken (ve herhangi bir POSIX uyumlu kabuk) üç durumdan birinde olabilir:

  • unset
  • boş dizeye ayarlamak
  • boş olmayan bir dizeye ayarlamak

Çoğu zaman yalnızca bir değişkenin boş olmayan bir dizeye ayarlanıp ayarlanmadığını bilmeniz gerekir, ancak bazen unset ve boş dizgiyi ayırmak önemlidir.

Aşağıdakiler, çeşitli olasılıkları nasıl test edebileceğinize ilişkin örnekler olup, bash veya POSIX uyumlu herhangi bir kabukta çalışır:

if [ -z "${VAR}" ]; then
    echo "VAR is unset or set to the empty string"
fi
if [ -z "${VAR+set}" ]; then
    echo "VAR is unset"
fi
if [ -z "${VAR-unset}" ]; then
    echo "VAR is set to the empty string"
fi
if [ -n "${VAR}" ]; then
    echo "VAR is set to a non-empty string"
fi
if [ -n "${VAR+set}" ]; then
    echo "VAR is set, possibly to the empty string"
fi
if [ -n "${VAR-unset}" ]; then
    echo "VAR is either unset or set to a non-empty string"
fi

İşte aynı şey ama kullanışlı masa şeklinde:

                        +-------+-------+-----------+
                VAR is: | unset | empty | non-empty |
+-----------------------+-------+-------+-----------+
| [ -z "${VAR}" ]       | true  | true  | false     |
| [ -z "${VAR+set}" ]   | true  | false | false     |
| [ -z "${VAR-unset}" ] | false | true  | false     |
| [ -n "${VAR}" ]       | false | false | true      |
| [ -n "${VAR+set}" ]   | false | true  | true      |
| [ -n "${VAR-unset}" ] | true  | false | true      |
+-----------------------+-------+-------+-----------+

${VAR+foo}Eğer yapı boş dizeye genişler VARayarlanmazsa veya fooeğer VARbir şey olarak ayarlanır (boş dize dahil).

${VAR-foo}Yapı değerine kadar genişler VARset (boş bir dizeye ayarlanmış dahil) ve eğer foosertleşmemiş halinde. Bu, kullanıcı tarafından geçersiz kılınabilen varsayılanları sağlamak için kullanışlıdır (örneğin, değişken bir şeye ayarlanmadıkça ${COLOR-red}kullanma der ).redCOLOR

Nedeni [ x"${VAR}" = x ]bazı uygulamaları nedeniyle sık sık değişken ayarlanmazsa veya boş bir dizeye ayarlanmış ya olup olmadığını test etmek için tavsiye edilir olduğu [(olarak da bilinir komutu test) arabası vardır. Eğer VARböyle bir şeye ayarlanmışsa -n, bazı uygulamalar hatalı yapıldığında yanlış bir şey yapacaktır, [ "${VAR}" = "" ]çünkü ilk argüman bir dize değil [, -noperatör olarak yanlış yorumlanmıştır .


3
Boş dizgiye ayarlanmış bir değişkenin testi de kullanılarak yapılabilir [ -z "${VAR-set}" ].
nwellnhof

@nwellnhof: Teşekkürler! Brifon sözdizimini kullanmak için cevabımı güncelledim.
Richard Hansen

İlk ve son yapı arasındaki fark nedir? Her ikisi de "VAR ayarlanmamış veya boş olmayan bir dizeye ayarlanmış" ifadesine karşılık gelir.
Faheem Mitha

1
@FaheemMitha: Bu senin hatan değil - cevabımı okumak zordu. Cevabı daha net hale getirmek için bir tablo ekledim.
Richard Hansen,

2
Ayarlanmamış çekler güvenilir değildir. Eğer kullanıcı aradıysa set -uveya set -o nounsetbash ise, test sadece "bash: VAR: unbound değişken" hatasıyla sonuçlanacaktır. Daha güvenilir bir ayarsız kontrol için bkz. Stackoverflow.com/a/13864829 . Go-to-değişken bir null olup olmadığını kontrol etmek veya unset olup olmadığını [ -z "${VAR:-}" ]. Bir değişkenin boş olmadığını kontrol ediyorum [ "${VAR:-}" ].
Kevin Jin

38

-z en iyi yol budur.

Kullandığım diğer seçenekler değişken ayarlamak, ancak başka bir değişken tarafından geçersiz kılınabilir.

export PORT=${MY_PORT:-5432}

Eğer $MY_PORTdeğişken boşsa PORTaksi PORT değerine ayarlanır, 5432 ayarlı alır MY_PORT. Sözdiziminde iki nokta üst üste ve kısa çizgi bulunur.


Yanlışlıkla bugün bunu buldum ve istediğim buydu. Teşekkürler! set -o nounsetBazı senaryolara katlanmak zorundayım .
opello

24

Set-empty-unset durumu durumlarını ayırt etmekle ilgileniyorsanız, bash için -u seçeneğine bakın:

$ set -u
$ echo $BAR
bash: BAR: unbound variable
$ [ -z "$BAR" ] && echo true
bash: BAR: unbound variable
$ BAR=""
$ echo $BAR

$ [ -z "$BAR" ] && echo true
true

8

Gördüğüm bir alternatif [ -z "$foo" ]şudur, ancak insanların neden bu yöntemi kullandıklarından emin değilim, herkes biliyor?

[ "x${foo}" = "x" ]

Her neyse, ayarlanmamış değişkenleri (ya da ya set -uda set -o nounset) reddediyorsanız , o zaman bu iki yöntemde de sorun yaşayacaksınız. Bunun basit bir çözümü var:

[ -z "${foo:-}" ]

Not: Bu değişkeninizi undef bırakacaktır.


3
Alternatifler hakkında pubs.opengroup.org/onlinepubs/009695399/utilities/test.html-z adresinde yorum yapıldı . Temel olarak, bunun bir alternatifi olmadığı anlamına gelmez -z. Daha ziyade, $foobir meta karakteriyle başlayan [veya testkarışması gereken bir şeye genişleyebilecek durumlarla ilgilenir . Rasgele bir meta karakter olmayanı başlangıçta koymak, bu olasılığı ortadan kaldırır.
James Sneeringer,

6

Soru sorar bir değişken boş bir dize olup olmadığını kontrol etmek nasıl ve en iyi cevapları Zaten bunun için verilmiştir.
Fakat bir süre php ile programlamayı geçtikten sonra buraya inmiştim ve aslında aradığım şey php'deki bash kabuğundaki boş fonksiyon gibi bir kontrol .
Cevapları okuduktan sonra, bash'da düzgün düşünmediğimi fark ettim, ama o an php'da boş gibi bir fonksiyon bash kodumda çok kullanışlı olurdu.
Bunun diğerlerinden başına gelebilecek düşünürken, bash php boş fonksiyonunu dönüştürmek için karar

uyarınca php kılavuzu :
değişken yoksa veya değeri aşağıdakilerden biriyse boş kabul edilir:

  • "" (boş bir dize)
  • 0 (bir tam sayı olarak 0)
  • 0.0 (0 şamandıra olarak)
  • "0" (dizge olarak 0)
  • boş bir dizi
  • bildirilen ancak değeri olmayan bir değişken

Tabii ki boş ve yanlış durumlar bash olarak dönüştürülemez, bu nedenle ihmal edilir.

function empty
{
    local var="$1"

    # Return true if:
    # 1.    var is a null string ("" as empty string)
    # 2.    a non set variable is passed
    # 3.    a declared variable or array but without a value is passed
    # 4.    an empty array is passed
    if test -z "$var"
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is zero (0 as an integer or "0" as a string)
    elif [ "$var" == 0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is 0.0 (0 as a float)
    elif [ "$var" == 0.0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return
    fi

    [[ $( echo "" ) ]]
}



Kullanım örneği:

if empty "${var}"
    then
        echo "empty"
    else
        echo "not empty"
fi



Demo:
aşağıdaki pasaj:

#!/bin/bash

vars=(
    ""
    0
    0.0
    "0"
    1
    "string"
    " "
)

for (( i=0; i<${#vars[@]}; i++ ))
do
    var="${vars[$i]}"

    if empty "${var}"
        then
            what="empty"
        else
            what="not empty"
    fi
    echo "VAR \"$var\" is $what"
done

exit

çıktılar:

VAR "" is empty
VAR "0" is empty
VAR "0.0" is empty
VAR "0" is empty
VAR "1" is not empty
VAR "string" is not empty
VAR " " is not empty

Bir bash mantığında, bu işlevdeki sıfır üzerindeki çeklerin yan sorunlara neden olabileceğini söyleyerek, bu işlevi kullanan herkes bu riski değerlendirmeli ve belki de yalnızca ilkini bırakarak bu çekleri kesmeye karar vermelidir.


Fonksiyonun içinde empty- neden [[ $( echo "1" ) ]] ; returnbasitçe yazdınız return 1?
Dor

5

if-then ve -z'nin tamamı gereksizdir.

["$ foo"] && echo "foo boş değil"
["$ foo"] || yankı "foo gerçekten boş"

3
Foo sadece boşluklar içeriyorsa başarısız olur
Brian 21

2
Foo bir seçenek olarak yorumlandığından bir çizgi ile başlarsa bazı kabuklarda da başarısız olur . Örneğin, solaris ksh , zsh ve bash sorun değil, sh ve / bin / test başarısız olacak
ktf 20:11

4

Bu tam olarak $ FOO ayarlanmış ve boşken geçerlidir:

[ "${FOO+x}" = x ] && [ -z "$FOO" ]

4

Şahsen kontrol etmek için daha net bir yol tercih et:

if [ "${VARIABLE}" == "" ]; then
  echo VARIABLE is empty
else
  echo VARIABLE is not empty
fi

1
Bazı mermiler çift eşittir işaretini kabul etmemektedir.
Dennis Williamson,

1
Soru bash ile ilgiliydi. Ben bash kullanıyorum. Benim için iyi çalışıyor. Tam olarak ne hakkında konuşuyorsun?
Fedir RYKHTIK

2
Bash kullanıyorsanız, çift köşeli ayraç kullanmalısınız. Benim önceki yorumum, cevabınızı okuyan ve farklı bir kabuk kullananlar için basit bir gerçek beyanıydı.
Dennis Williamson,

tek köşeli parantezler bu durumda tamamdır, lütfen serverfault.com/questions/52034/…
Luca Borrione

4

arasında oneliner uzantısı duffbeer703 'in çözeltisi:

#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter

4

5 sentim: Bundan daha kısa bir sözdizimi de var if ...:

VALUE="${1?"Usage: $0 value"}"

Bir argüman sağlandıysa, bu satır VALUE olarak belirlenir ve bir hata olması durumunda komut satırı satırıyla birlikte hazırlanmış bir hata mesajı basar (ve komut çalıştırmasını sonlandırır).

Başka bir örnek abs-rehberinde bulunabilir («Örnek 10-7» için arama yapın).


0

Kesin bir cevap değil, ama bu numaraya rastladım. Eğer aradığınız dize "bir komuttan" geliyorsa, o zaman komutu bir env içinde saklayabilirsiniz. değişken ve ardından if ifadesi için her seferinde uygulayın, sonra parantez gerekmez!

Örneğin debian olup olmadığınızı belirleyen bu komut:

grep debian /proc/version

tam örnek:

IS_DEBIAN="grep -i debian /proc/version"

if $IS_DEBIAN; then
  echo 'yes debian'
else
  echo 'non debian'
fi

Bu, boş bir dize (her komuttan tekrarlanan) için boş bir dize denetleme (komuttan hata yanıtını denetleme olur, ancak boş bir dize döndürme olur) gibi dolaylı bir yol gibidir.

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.