उपयोग न करना बनाम खाली करने के लिए एक चर सेट करना


108

मैं वर्तमान में एक बैश परीक्षण रूपरेखा लिख ​​रहा हूं, जहां एक परीक्षण समारोह में, दोनों मानक बैश परीक्षण ( [[) के साथ-साथ पूर्वनिर्धारित मिलानकर्ताओं का उपयोग किया जा सकता है। मैचर्स '[[' के लिए रैपर हैं और रिटर्न कोड लौटाने के अलावा, कुछ सार्थक संदेश सेट करते हैं, जो अपेक्षित था।

उदाहरण:

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

            return 1
    fi
}

इसलिए, जब एक माचिस का उपयोग किया जाता है, और यह विफल हो जाता है, तभी एक error_message सेट किया जाता है।

अब, कुछ समय बाद, मैं परीक्षण करता हूं कि क्या परीक्षण सफल हुए। यदि यह सफल हुआ, तो मैं हरे रंग में उम्मीद को प्रिंट करता हूं, अगर यह लाल रंग में विफल रहा।

इसके अलावा, एक error_message सेट हो सकता है, इसलिए मैं परीक्षण करता हूं यदि कोई संदेश मौजूद है, तो उसे प्रिंट करें, और फिर उसे अनसेट करें (क्योंकि निम्नलिखित परीक्षण सेट नहीं हो सकता है error_message):

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

    unset -v error_message
fi

अब मेरा सवाल यह है कि अगर वेरिएबल को अनसेट करना बेहतर है, या सिर्फ इसे '' जैसे सेट करना है

error_message=''

इनमे से कौन बेहतर है? क्या वास्तव में इससे कोई फर्क पड़ता है? या हो सकता है कि मेरे पास एक अतिरिक्त ध्वज होना चाहिए जो यह दर्शाता है कि संदेश सेट किया गया था?


1
यदि आप कभी error_messageकिसी और चीज के साथ तुलना नहीं करते हैं , तो मैं कहूंगा कि इससे कोई फर्क नहीं पड़ता। हालाँकि, मुझे लगता है कि आप चाहते हैं [[ $error_message ]], अन्यथा आप परीक्षण कर रहे हैं कि शाब्दिक स्ट्रिंग "error_message" मौजूद है।
शेपनर

@chepner हाँ, एक टाइपो था। ठीक कर दिया।
हेल्परमेथोड 14

जवाबों:


143

जब तक आप उपयोग नहीं कर रहे हैं, अधिकतर आपको कोई अंतर दिखाई नहीं देता है 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

तो वास्तव में, यह इस बात पर निर्भर करता है कि आप चर का परीक्षण कैसे करने जा रहे हैं।

अगर यह सेट है तो मैं परीक्षण का अपना पसंदीदा तरीका जोड़ूंगा:

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

या

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

43
var="सेट नहीं है"। यह सिर्फ एक निर्विवाद रिक्त स्ट्रिंग है। इसके अलावा set -u, बैश के विभिन्न प्रकार के पैरामीटर विस्तार भी परेशान और अशक्त मूल्यों के बीच अंतर कर सकते हैं: ${foo:bar}जब fooपरेशान होता है, तो "बार" में फैलता है , लेकिन "जब fooअशक्त होता है, जबकि ${foo:-bar}" बार "में फैलता है अगर फू परेशान या अशक्त है।
शेपनर

1
[[ -n $var ]]varखाली स्ट्रिंग पर सेट होने पर गलत है।
शेपनर

1
यदि आप वेरिएबल 'अस्तित्व' की जाँच के लिए 'डिक्लेयर -p' का उपयोग करते हैं, तो var = 'डिक्लेयर - var = "को दिखाएगा" "आपको इससे छुटकारा पाने के लिए unset का उपयोग करना होगा, निश्चित रूप से यदि इसका एक आसानी से वैरिएबल है तो आप नहीं मिल सकते इससे छुटकारा। इसके अलावा, यदि आप किसी फ़ंक्शन के अंदर var = कुछ करते हैं, तो आपको इससे छुटकारा पाने के बारे में चिंता करना होगा यदि आप "स्थानीय var = value" का उपयोग करते हैं, हालांकि सावधान रहें, क्योंकि "var var = value" भी स्थानीय है। घोषित करने के मामले में आपको स्पष्ट रूप से "डिक्लेयर -g var = value" का उपयोग करके इसे वैश्विक रूप से सेट करना होगा, बिना डिक्लेयर किए आपको स्पष्ट रूप से इसे "लोकल" का उपयोग करके स्थानीय रूप से सेट करना होगा। Global var केवल मिटाए गए / w unset हैं।
ओसिरिसगोथरा

@osirisgothra: स्थानीय चरों के बारे में अच्छी बात। बेशक आम तौर पर किसी फ़ंक्शन में सभी चर घोषित करना (या स्थानीयकरण) करना सबसे अच्छा है, ताकि यह संक्षिप्त हो।
cdarke

3
@chepner होना चाहिए ${foo-bar}बजाय ${foo:bar}। खुद के लिए परीक्षण:unset a; echo ">${a:-foo}-${a:foo}-${a-foo}<"
Liviu Chircu

17

जैसा कि कहा गया है, ऐसेट्स का उपयोग ऐरे के साथ भी अलग है

$ foo=(4 5 6)

$ foo[2]=

$ echo ${#foo[*]}
3

$ unset foo[2]

$ echo ${#foo[*]}
2

2

तो, ऐरे इंडेक्स 2 को असम्बद्ध करके, आप अनिवार्य रूप से एरे में उस एलीमेंट को हटाते हैं और ऐरे साइज़ () को घटाते हैं।

मैंने अपना टेस्ट खुद किया ।।

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

जिसके परिणामस्वरूप..

3
0

तो बस स्पष्ट करने के लिए कि पूरे सरणी को खोलना वास्तव में इसे पूरी तरह से हटा देगा।


0

उपरोक्त टिप्पणियों के आधार पर, यहां एक सरल परीक्षण दिया गया है:

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

उदाहरण:

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