ध्यान दें
मैं bash
टैग के कारण भारी बैश-केंद्रित उत्तर दे रहा हूं ।
संक्षिप्त जवाब
जब तक आप केवल बैश में नामांकित चर के साथ काम कर रहे हैं, तब तक यह फ़ंक्शन आपको हमेशा बताएगा कि क्या चर सेट किया गया है, भले ही वह खाली सरणी हो।
variable-is-set() {
declare -p "$1" &>/dev/null
}
यह क्यों काम करता है
बैश में (कम से कम 3.0 के रूप में वापस), अगर var
एक घोषित / सेट चर है, तो declare -p var
एक declare
कमांड को आउटपुट करता var
है जो चर को उसके वर्तमान प्रकार और मूल्य के लिए सेट करेगा , और स्थिति कोड 0
(सफलता) देता है। यदि var
अघोषित है, तो स्थिति कोड declare -p var
को एक त्रुटि संदेश आउटपुट करता है । का उपयोग करते हुए , नियमित और आउटपुट दोनों को रीडायरेक्ट करता हैstderr
1
&>/dev/null
stdout
stderr
/dev/null
, कभी नहीं देखा जा सकता है, और स्थिति कोड को बदले बिना। इस प्रकार फ़ंक्शन केवल स्थिति कोड लौटाता है।
क्यों बाश में अन्य तरीके (कभी-कभी) विफल हो जाते हैं
[ -n "$var" ]
: यह केवल जाँच करता है कि ${var[0]}
क्या गैर-रिक्त है। (बैश में, $var
जैसा है ${var[0]}
)
[ -n "${var+x}" ]
: यह केवल जाँच करता है कि ${var[0]}
क्या सेट है।
[ "${#var[@]}" != 0 ]
: यह केवल जाँच करता है कि कम से कम एक इंडेक्स $var
सेट है या नहीं।
जब यह विधि बैश में विफल हो जाती है
यह केवल नामित चरों (सहित के लिए काम करता है $_
), नहीं कुछ विशेष चर ( $!
, $@
, $#
, $$
, $*
, $?
, $-
, $0
, $1
, $2
, ..., और किसी भी मैं भूल गए हैं सकता है)। चूँकि इनमें से कोई भी सारणी नहीं है, POSIX- शैली [ -n "${var+x}" ]
इन सभी विशेष चरों के लिए काम करती है। लेकिन फ़ंक्शन में इसे लपेटने से सावधान रहें क्योंकि कई विशेष चर मूल्यों / अस्तित्व को बदलते हैं जब फ़ंक्शन कहलाते हैं।
शेल संगतता नोट
यदि आपकी स्क्रिप्ट में सरणियाँ हैं और आप इसे यथासंभव अधिक गोले के साथ संगत बनाने का प्रयास कर रहे हैं, तो typeset -p
इसके बजाय का उपयोग करने पर विचार करें declare -p
। मैंने पढ़ा है कि ksh केवल पूर्व का समर्थन करता है, लेकिन यह परीक्षण करने में सक्षम नहीं है। मुझे पता है कि बैश 3.0+ और Zsh 5.5.1 दोनों प्रत्येक समर्थन करते हैं typeset -p
और declare -p
, केवल अलग-अलग होते हैं जिसमें एक दूसरे के लिए एक विकल्प है। लेकिन मैंने उन दो खोजशब्दों के अंतरों का परीक्षण नहीं किया है, और मैंने अन्य गोले का परीक्षण नहीं किया है।
यदि आपको अपनी स्क्रिप्ट को POSIX sh संगत बनाने की आवश्यकता है, तो आप सरणियों का उपयोग नहीं कर सकते। बिना एरे के, [ -n "{$var+x}" ]
काम करता है।
बैश में विभिन्न तरीकों के लिए तुलना कोड
यह फ़ंक्शन चर कोड को अनसेट करता है var
, eval
पास कोड को चलाता है, यह निर्धारित करने के लिए परीक्षण चलाता है कि क्या डी कोड var
द्वारा निर्धारित किया गया है eval
, और अंत में विभिन्न परीक्षणों के लिए परिणामी स्थिति कोड दिखाता है।
मैं लंघन कर रहा हूँ test -v var
, [ -v var ]
और [[ -v var ]]
क्योंकि वे POSIX मानक के समान परिणाम[ -n "${var+x}" ]
, बैश 4.2+ की आवश्यकता होती है, जबकि। मैं लंघन भी कर रहा हूँ typeset -p
क्योंकि यह declare -p
मेरे द्वारा परीक्षण किए गए गोले के रूप में ही है (बैश 3.0 के माध्यम से 5.0, और Zsh 5.5.1)।
is-var-set-after() {
# Set var by passed expression.
unset var
eval "$1"
# Run the tests, in increasing order of accuracy.
[ -n "$var" ] # (index 0 of) var is nonempty
nonempty=$?
[ -n "${var+x}" ] # (index 0 of) var is set, maybe empty
plus=$?
[ "${#var[@]}" != 0 ] # var has at least one index set, maybe empty
count=$?
declare -p var &>/dev/null # var has been declared (any type)
declared=$?
# Show test results.
printf '%30s: %2s %2s %2s %2s\n' "$1" $nonempty $plus $count $declared
}
टेस्ट केस कोड
ध्यान दें कि बैश नॉन-न्यूमेरिक ऐरे इंडिकेशंस को "0" मानने के कारण टेस्ट रिजल्ट अप्रत्याशित हो सकता है, अगर वेरिएबल को ऐररेटिव ऐरे के रूप में घोषित नहीं किया गया है। इसके अलावा, सहयोगी एरे केवल बश 4.0+ में मान्य हैं।
# Header.
printf '%30s: %2s %2s %2s %2s\n' "test" '-n' '+x' '#@' '-p'
# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an
# indexed array is also the nonindexed value, and non-numerical
# indices in an array not declared as associative are the same as
# index 0.
is-var-set-after "var=foo" # 0 0 0 0
is-var-set-after "var=(foo)" # 0 0 0 0
is-var-set-after "var=([0]=foo)" # 0 0 0 0
is-var-set-after "var=([x]=foo)" # 0 0 0 0
is-var-set-after "var=([y]=bar [x]=foo)" # 0 0 0 0
# '[ -n "$var" ]' fails when var is empty.
is-var-set-after "var=''" # 1 0 0 0
is-var-set-after "var=([0]='')" # 1 0 0 0
# Indices other than 0 are not detected by '[ -n "$var" ]' or by
# '[ -n "${var+x}" ]'.
is-var-set-after "var=([1]='')" # 1 1 0 0
is-var-set-after "var=([1]=foo)" # 1 1 0 0
is-var-set-after "declare -A var; var=([x]=foo)" # 1 1 0 0
# Empty arrays are only detected by 'declare -p'.
is-var-set-after "var=()" # 1 1 1 0
is-var-set-after "declare -a var" # 1 1 1 0
is-var-set-after "declare -A var" # 1 1 1 0
# If 'var' is unset, then it even fails the 'declare -p var' test.
is-var-set-after "unset var" # 1 1 1 1
परीक्षण उत्पादन
शीर्ष लेख पंक्ति के अनुरूप में परीक्षण स्मृति सहायकों के लिए [ -n "$var" ]
, [ -n "${var+x}" ]
, [ "${#var[@]}" != 0 ]
, और declare -p var
, क्रमशः।
test: -n +x #@ -p
var=foo: 0 0 0 0
var=(foo): 0 0 0 0
var=([0]=foo): 0 0 0 0
var=([x]=foo): 0 0 0 0
var=([y]=bar [x]=foo): 0 0 0 0
var='': 1 0 0 0
var=([0]=''): 1 0 0 0
var=([1]=''): 1 1 0 0
var=([1]=foo): 1 1 0 0
declare -A var; var=([x]=foo): 1 1 0 0
var=(): 1 1 1 0
declare -a var: 1 1 1 0
declare -A var: 1 1 1 0
unset var: 1 1 1 1
सारांश
declare -p var &>/dev/null
(100%?) कम से कम 3.0 के बाद से बैश में चर नाम के परीक्षण के लिए विश्वसनीय है।
[ -n "${var+x}" ]
POSIX आज्ञाकारी स्थितियों में विश्वसनीय है, लेकिन सरणियों को संभाल नहीं सकता है।
- अन्य परीक्षण यह जाँचने के लिए मौजूद हैं कि क्या कोई चर अ-रिक्त है, और अन्य गोले में घोषित चर के लिए जाँच के लिए। लेकिन ये परीक्षण न तो बैश और न ही पॉसिक्स स्क्रिप्ट के लिए अनुकूल हैं।
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi
।