Kodlarda değişken ataması için “$ {a: -b}” kullanımı


425

Diğer insanların yazdığı birkaç senaryoya bakıyordum (özellikle Red Hat) ve değişkenlerinin çoğu aşağıdaki gösterim kullanılarak atanmış VARIABLE1="${VARIABLE1:-some_val}" veya bazıları diğer değişkenleri genişletmiş VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

Yalnızca bu değerleri doğrudan beyan etmek yerine (ör. VARIABLE1=some_val) Bu gösterimi kullanmanın amacı nedir?

Bu gösterimin faydaları veya önlenebilecek olası hatalar var mı?

:-Bu bağlamda özel bir anlamı var mı ?


Bir göz atın man bash; "Parametre Genişletme" bloğunu arayın (yaklaşık% 28'de). Bu atamalar örneğin varsayılan işlevlerdir: "Henüz ayarlanmamışsa varsayılan değeri kullanın."
Hauke ​​Laging

Yanıtlar:


693

Bu teknik, başka bir değişken boşsa veya tanımsızsa, bir değişkene değer atanmasına izin verir. NOT: Bu "diğer değişken" aynı veya başka bir değişken olabilir.

alıntı

${parameter:-word}
    If parameter is unset or null, the expansion of word is substituted. 
    Otherwise, the value of parameter is substituted.

Not: Bu form aynı zamanda çalışır ${parameter-word}. Bash içerisinde bulunan tüm parametre genişletme türlerinin tam bir listesini görmek isterseniz, bu konuya Bash Hacker'ın wiki'sinde " Parameter genişletme " konusuna bir göz atmanızı şiddetle tavsiye ederim .

Örnekler

değişken yok
$ echo "$VAR1"

$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
default value
değişken var
$ VAR1="has value"
$ echo "$VAR1"
has value

$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
has value

Aynı şey, diğer değişkenleri değerlendirerek veya gösterimin varsayılan değer bölümünde komutları çalıştırarak da yapılabilir.

$ VAR2="has another value"
$ echo "$VAR2"
has another value
$ echo "$VAR1"

$

$ VAR1="${VAR1:-$VAR2}"
$ echo "$VAR1"
has another value

Daha fazla örnek

Sadece olduğu yerde biraz farklı bir gösterim de kullanabilirsiniz VARX=${VARX-<def. value>}.

$ echo "${VAR1-0}"
has another value
$ echo "${VAR2-0}"
has another value
$ echo "${VAR3-0}"
0

Yukarıdakilerde $VAR1& $VAR2zaten "başka bir değere sahip" $VAR3dizgisiyle tanımlandı, ancak tanımsızdı, bu nedenle varsayılan değer yerine kullanıldı 0.

Başka bir örnek

$ VARX="${VAR3-0}"
$ echo "$VARX"
0

:=Notasyon kullanarak kontrol etme ve atama

Son olarak kullanışlı operatörden bahsedeceğim :=. Test edilen değişken boş veya tanımsız ise bu işlem kontrol eder ve bir değer atar.

Örnek

$VAR1Şimdi ayarlanmış dikkat edin . Operatör :=testi ve ödevi tek bir işlemle yaptı.

$ unset VAR1
$ echo "$VAR1"

$ echo "${VAR1:=default}"
default
$ echo "$VAR1"
default

Ancak değer önceden ayarlanmışsa, yalnız kalır.

$ VAR1="some value"
$ echo "${VAR1:=default}"
some value
$ echo "$VAR1"
some value

Handy Dandy Referans Masası

    Tablo ss

Referanslar


8
Bunların hepsinin genişleme olmadığına dikkat edin bash. ${var:-word}Q biridir, fakat ${var-word}yukarıda. POSIX belgelerinin güzel bir masaya sahip olmasına rağmen, bu cevaba kopyalamaya değebilir
Graeme

5
@Graeme belgelenmiştir, sadece kolonun çıkarılması sonucuna
Stéphane Chazelas

7
echo "${FOO:=default}"Gerçekten istiyorsanız, kullanmak harika echo. Ama yapmazsan, :yerleşik yapmayı dene ... : ${FOO:=default} Siz yukarıdaki gibi $FOOayarlanmışsınız default(yani önceden ayarlanmamışsa). Fakat $FOObu süreçte yankı yok .
fbicknel

2
Tamam, bir cevap buldum: stackoverflow.com/q/24405606/1172302 . Kullanma ${4:-$VAR}irade işi.
Nikos Alexandris

1
Burada, seni 500'e getirmek için bir + 1'in var. Tebrikler! :)
XtraSimplicity

17

@slm zaten çok faydalı olan POSIX belgelerini zaten içeriyor, ancak bu parametrelerin birbirlerini etkilemek için nasıl bir araya getirilebileceğini gerçekten genişletmiyorlar. Bu formdan henüz bahsedilmedi:

${var?if unset parent shell dies and this message is output to stderr}

Bu benim başka bir cevabımdan bir alıntı , ve bence bu işlerin nasıl yürüdüğünü çok iyi gösteriyor:

    sh <<-\CMD
    _input_fn() { set -- "$@" #redundant
            echo ${*?WHERES MY DATA?}
            #echo is not necessary though
            shift #sure hope we have more than $1 parameter
            : ${*?WHERES MY DATA?} #: do nothing, gracefully
    }
    _input_fn heres some stuff
    _input_fn one #here
    # shell dies - third try doesnt run
    _input_fn you there?
    # END
    CMD
heres some stuff
one
sh: line :5 *: WHERES MY DATA?

Aynı başka bir örnek :

    sh <<-\CMD
    N= #N is NULL
    _test=$N #_test is also NULL and
    v="something you would rather do without"    
    ( #this subshell dies
        echo "v is ${v+set}: and its value is ${v:+not NULL}"
        echo "So this ${_test:-"\$_test:="} will equal ${_test:="$v"}"
        ${_test:+${N:?so you test for it with a little nesting}}
        echo "sure wish we could do some other things"
    )
    ( #this subshell does some other things 
        unset v #to ensure it is definitely unset
        echo "But here v is ${v-unset}: ${v:+you certainly wont see this}"
        echo "So this ${_test:-"\$_test:="} will equal NULL ${_test:="$v"}"
        ${_test:+${N:?is never substituted}}
        echo "so now we can do some other things" 
    )
    #and even though we set _test and unset v in the subshell
    echo "_test is still ${_test:-"NULL"} and ${v:+"v is still $v"}"
    # END
    CMD
v is set: and its value is not NULL
So this $_test:= will equal something you would rather do without
sh: line 7: N: so you test for it with a little nesting
But here v is unset:
So this $_test:= will equal NULL
so now we can do some other things
_test is still NULL and v is still something you would rather do without

Yukarıdaki örnek POSIX parametre yerine her 4 formları yararlanır ve bunların çeşitli :colon nullveya not nulltestleri. Yukarıdaki linkte daha fazla bilgi var ve işte yine burada .

İnsanların sık sık düşünmediği bir başka şey, ${parameter:+expansion}burada bir belgede ne kadar faydalı olabileceğidir. İşte farklı bir cevaptan başka bir alıntı :

ÜST, EN İYİ, TEPE

Burada bazı varsayılanları ayarlayacak ve çağrıldığında bunları yazdırmaya hazırlayacaksınız ...

#!/bin/sh
    _top_of_script_pr() ( 
        IFS="$nl" ; set -f #only split at newlines and don't expand paths
        printf %s\\n ${strings}
    ) 3<<-TEMPLATES
        ${nl=
}
        ${PLACE:="your mother's house"}
        ${EVENT:="the unspeakable."}
        ${ACTION:="heroin"}
        ${RESULT:="succeed."}
        ${strings:="
            I went to ${PLACE} and saw ${EVENT}
            If you do ${ACTION} you will ${RESULT}
        "}
    #END
    TEMPLATES

ORTA

Bu, sonuçlarına göre yazdırma işlevinizde çağrılacak diğer işlevleri tanımladığınız yerdir ...

    EVENT="Disney on Ice."
    _more_important_function() { #...some logic...
        [ $((1+one)) -ne 2 ] && ACTION="remedial mathematics"
            _top_of_script_pr
    }
    _less_important_function() { #...more logic...
        one=2
        : "${ACTION:="calligraphy"}"
        _top_of_script_pr
    }

ALT

Artık her şeyi ayarladınız, işte sonuçlarınızı uygulayacağınız ve çekeceğiniz yer burasıdır.

    _less_important_function
    : "${PLACE:="the cemetery"}" 
    _more_important_function
    : "${RESULT:="regret it."}" 
    _less_important_function    

SONUÇLAR

Neden bir dakika sonra gireceğim, ancak yukarıdakileri çalıştırmanız aşağıdaki sonuçları veriyor:

_less_important_function()'s ilk çalıştırma:

Annenin evine gittim ve Disney on Ice'ı gördüm .

Eğer hat sanatı yaparsan, başaracaksın.

sonra _more_important_function():

Mezarlığa gittim ve Disney on Ice'ı gördüm.

Eğer düzeltici matematiği yaparsan, başaracaksın.

_less_important_function() tekrar:

Mezarlığa gittim ve Disney on Ice'ı gördüm.

Düzeltici matematiği yaparsanız pişman olacaksınız .

NASIL ÇALIŞIR:

Buradaki en önemli özellik, conditional ${parameter} expansion.bir değişkeni ancak formu kullanarak ayarlanmamış veya boş olması durumunda bir değere ayarlayabilirsiniz:

${var_name: =desired_value}

Bunun yerine sadece belirsiz bir değişken ayarlamak isterseniz, ihmal eder :colonve boş değerler olduğu gibi kalır.

KAPSAMDA:

Yukarıdaki örnekteki fark edebilirsiniz $PLACEve $RESULTüzeri ayarlandığında değişti parameter expansionolsa bile _top_of_script_pr()o yayınlandığında, bir muhtemelen onları ayarlayarak, zaten adı olmuştur. Bunun işe yaramasının sebebi _top_of_script_pr()bir ( subshelled )fonksiyon - başkaları parensiçin { curly braces }kullanmak yerine onu içine aldım . Alt kabuk olarak adlandırıldığından, ayarladığı her değişkendir locally scopedve ana kabuğuna döndüğünde bu değerler kaybolur.

Ancak _more_important_function()kümeler $ACTIONböyle olunca ikinci değerlendirmeyi globally scopedetkiler çünkü kümeler sadece üzerinden_less_important_function()'s$ACTION_less_important_function()$ACTION${parameter:=expansion}.



8

Kişisel deneyim.

Bu formatı bazen senaryolarımda geçici olarak fazla değer aşmak için kullanırım, örneğin:

$ cat script.sh
SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING"; 

Koşabilirim:

$ env SOMETHING="something other than the default value" ./script.sh` 

orijinal varsayılan değerini değiştirmek zorunda kalmadan SOMETHING.

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.