लिपियों में चर असाइनमेंट के लिए "$ {a: -b}" का उपयोग करना


426

मैं कुछ लिपियों को देख रहा हूं जो अन्य लोगों ने लिखी हैं (विशेष रूप से रेड हैट), और उनके बहुत सारे चर निम्नलिखित संकेतन का उपयोग करके असाइन किए गए हैं VARIABLE1="${VARIABLE1:-some_val}" या कुछ अन्य चर का विस्तार करते हैं VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

केवल सीधे मूल्यों (जैसे, VARIABLE1=some_val) की घोषणा करने के बजाय इस अंकन का उपयोग करने का क्या मतलब है ?

क्या इस अंकन या संभावित त्रुटियों के लिए लाभ हैं जिन्हें रोका जाएगा?

क्या :-इस संदर्भ में विशिष्ट अर्थ है?


देख लो man bash; ब्लॉक "पैरामीटर विस्तार" की खोज करें (लगभग 28% पर)। ये असाइनमेंट उदाहरण के लिए डिफ़ॉल्ट फ़ंक्शंस हैं: "डिफ़ॉल्ट मान का उपयोग केवल तभी करें जब तक कि कोई भी सेट न किया गया हो।"
हौके लैजिंग

जवाबों:


695

यह तकनीक एक वैरिएबल को एक मान निर्दिष्ट करने की अनुमति देती है यदि कोई अन्य चर या तो खाली है या अपरिभाषित है। नोट: यह "अन्य चर" समान या दूसरा चर हो सकता है।

अंश

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

ध्यान दें: यह रूप भी काम करता है, ${parameter-word}। यदि आप बैश के भीतर उपलब्ध सभी प्रकार के पैरामीटर विस्तार की पूरी सूची देखना चाहते हैं, तो मेरा सुझाव है कि आप बैश हैकर के विकी शीर्षक में इस विषय पर एक नज़र डालें: " पैरामीटर विस्तार "।

उदाहरण

चर मौजूद नहीं है
$ echo "$VAR1"

$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
default value
चर मौजूद है
$ VAR1="has value"
$ echo "$VAR1"
has value

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

यही बात अन्य चर का मूल्यांकन करके या अंकन के डिफ़ॉल्ट मान भाग के भीतर आदेशों को चलाकर भी किया जा सकता है।

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

$

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

और ज्यादा उदाहरण

आप थोड़े अलग संकेतन का भी उपयोग कर सकते हैं जहाँ यह है VARX=${VARX-<def. value>}

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

इसके बाद के संस्करण में $VAR1और $VAR2पहले से ही स्ट्रिंग "एक और महत्व है" के साथ परिभाषित किया गया लेकिन $VAR3, अपरिभाषित था, तो डिफ़ॉल्ट मान के बजाय इस्तेमाल किया गया था 0

एक और उदाहरण

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

:=संकेतन का उपयोग करके जांचना और असाइन करना

अन्त में मैं, आसान ऑपरेटर उल्लेख करेंगे :=। यह जाँच करेगा और एक मान असाइन करेगा यदि परीक्षण के तहत चर खाली या अपरिभाषित है।

उदाहरण

नोटिस जो $VAR1अब सेट है। ऑपरेटर :=ने एक ही ऑपरेशन में परीक्षण और असाइनमेंट किया।

$ unset VAR1
$ echo "$VAR1"

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

हालाँकि यदि मूल्य पूर्व निर्धारित है, तो यह अकेला रह गया है।

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

काम बांका संदर्भ तालिका

    टेबल के एस.एस.

संदर्भ


8
ध्यान दें कि ये सभी विस्तार में प्रलेखित नहीं हैं bash${var:-word}क्यू में से एक है, लेकिन नहीं ${var-word}ऊपर। POSIX प्रलेखन की एक अच्छी तालिका है, हालांकि, इस उत्तर में इसे कॉपी करने के लायक हो सकता है - pubs.opengroup.org/onlinepubs/9699919799/utilities/…
ग्रीम

5
@Gememe, यह प्रलेखित है, आपको केवल एक पैरामीटर के परीक्षण में
स्टीफन चेज़लस

7
echo "${FOO:=default}"यदि आप वास्तव में चाहते हैं तो प्रयोग करना बहुत अच्छा है echo। लेकिन यदि आप नहीं करते हैं, तो :अंतर्निहित प्रयास करें ... : ${FOO:=default} आपका $FOOसेट defaultऊपर के रूप में सेट किया गया है (यानी, यदि पहले से सेट नहीं है)। लेकिन $FOOइस प्रक्रिया में कोई गूँज नहीं है।
fbicknel

2
ठीक है, एक उत्तर मिला: stackoverflow.com/q/24405606/1172302${4:-$VAR}वसीयत का उपयोग करना ।
निकोस अलेक्जेंड्रिस

1
यहाँ, आपको 500 लाने के लिए +1 है। बधाई हो! :)
XtraSimplicity 7

17

@ एसएलएम में पहले से ही पॉसिक्स डॉक्स शामिल हैं - जो बहुत सहायक हैं - लेकिन वे वास्तव में इस पर विस्तार नहीं करते हैं कि इन मापदंडों को एक दूसरे को प्रभावित करने के लिए कैसे जोड़ा जा सकता है। इस फॉर्म का यहाँ कोई उल्लेख नहीं है:

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

यह मेरा एक और जवाब है, और मुझे लगता है कि यह बहुत अच्छी तरह से दर्शाता है कि ये कैसे काम करते हैं:

    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?

उसी से एक और उदाहरण :

    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

उपरोक्त उदाहरण POSIX पैरामीटर प्रतिस्थापन के सभी 4 रूपों और उनके विभिन्न :colon nullया not nullपरीक्षणों का लाभ उठाता है । उपरोक्त लिंक में अधिक जानकारी है, और यहां यह फिर से है

एक और बात जो लोग अक्सर इस बारे ${parameter:+expansion}में विचार नहीं करते हैं कि यह यहां के दस्तावेज़ में कितना उपयोगी है। यहाँ एक अलग जवाब से एक और अंश है :

ऊपर

यहाँ आप कुछ डिफॉल्ट सेट करेंगे और उन्हें कॉल करने के लिए प्रिंट करने की तैयारी करेंगे ...

#!/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

मध्य

यह वह जगह है जहाँ आप अपने परिणामों के आधार पर अपने प्रिंट फ़ंक्शन पर कॉल करने के लिए अन्य कार्यों को परिभाषित करते हैं ...

    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
    }

तल

अब आपको यह सब सेटअप मिल गया है, इसलिए यहां आप अपने परिणामों को निष्पादित और खींच लेंगे।

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

परिणाम

मैं एक पल में क्यों अंदर जाऊंगा, लेकिन ऊपर चलने से निम्नलिखित परिणाम मिलते हैं:

_less_important_function()'s प्रथम रन:

मैं आपकी माँ के घर गया और बर्फ पर डिज्नी को देखा

यदि आप सुलेख करते हैं तो आप सफल होंगे।

फिर _more_important_function():

मैं कब्रिस्तान गया और बर्फ पर डिज्नी को देखा।

यदि आप सुधारात्मक गणित करेंगे तो आप सफल होंगे।

_less_important_function() फिर:

मैं कब्रिस्तान गया और बर्फ पर डिज्नी को देखा।

यदि आप उपचारात्मक गणित करते हैं तो आपको इसका पछतावा होगा।

यह काम किस प्रकार करता है:

यहाँ की प्रमुख विशेषता यह है कि conditional ${parameter} expansion.आप किसी वैरिएबल को किसी मान पर सेट कर सकते हैं, यदि यह फ़ॉर्म का उपयोग करने पर अशक्त या अशक्त हो:

${var_name: =desired_value}

यदि इसके बजाय आप केवल एक अस्थिर चर सेट करना चाहते हैं, तो आप छोड़ देंगे :colonऔर अशक्त मान जैसा है वैसा ही रहेगा।

SCOPE पर:

आप देख सकते हैं कि उपरोक्त उदाहरण में $PLACEऔर $RESULTपरिवर्तित होने के parameter expansionबावजूद सेट होने के बावजूद _top_of_script_pr()पहले से ही कॉल किया गया है, संभवत: इसे चलाने पर उन्हें सेट किया जा सकता है। इसका कारण यह है कि _top_of_script_pr()यह एक ( subshelled )फ़ंक्शन है - मैंने इसे दूसरों के लिए उपयोग किए जाने के parensबजाय संलग्न { curly braces }किया। क्योंकि इसे एक उपधारा में कहा जाता है, प्रत्येक चर जो इसे सेट करता है locally scopedऔर जैसे ही यह अपने मूल शेल में वापस आता है, वे मान गायब हो जाते हैं।

लेकिन जब _more_important_function()सेट $ACTIONहोता है globally scopedतो यह _less_important_function()'sदूसरे मूल्यांकन को प्रभावित करता है $ACTIONक्योंकि _less_important_function()सेट $ACTIONकेवल के माध्यम से होता है${parameter:=expansion}.


1
यह देखने के लिए अच्छा है कि शॉर्टहैंड डिफ़ॉल्ट मान बॉर्न शेल
श्रीधर सरनोबत

8

निजी अनुभव।

मैं इस प्रारूप का उपयोग कभी-कभी अपनी स्क्रिप्ट में मानों की अधिकता-सवारी करने के लिए करता हूं, जैसे कि यदि मेरे पास हो तो:

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

मैं दौड़ सकता हूं:

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

मूल डिफ़ॉल्ट मान को बदलने के लिए बिना SOMETHING

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.