यदि कोई चर I यदि ’कथन में मौजूद है, तो मैं कैसे जांच करूं?


69

मुझे एक ifबयान में एक चर के अस्तित्व की जांच करने की आवश्यकता है । के प्रभाव के लिए कुछ:

if [ -v $somevar ]
then
    echo "Variable somevar exists!"
else
    echo "Variable somevar does not exist!"

और उस के लिए निकटतम सवाल था इस , जो वास्तव में मेरे सवाल का जवाब नहीं है।


आप सेट करना चाहते हैं $somevar, तो चर मौजूद नहीं है एक मूल्य / स्ट्रिंग के लिए: ${somevar:=42}
सायरस

व्यक्तिगत रूप से, मैं सिर्फ शून्यता ( [ -n "$var" ]या [ ! -z "$var" ]) के लिए जाँच करता हूँ । मुझे लगता है कि अस्तित्व / अविश्वास की जाँच बहुत ही सूक्ष्म है, और मैं अपना कोड मोटे और सरल पसंद करता हूं।
PSkocik

आपको उस बनाम की आवश्यकता क्यों है [ -n "$var" ]? संबंधित: stackoverflow.com/questions/3601515/…
Ciro Santilli over .com/ .com/ .com/ 法轮功 六四

जवाबों:


97

आधुनिक बैश में (संस्करण 4.2 और ऊपर):

[[ -v name_of_var ]]

से help test:

-V VAR, यह सही है अगर शेल वैरिएबल VAR सेट है


3
इसके अलावा एकल ब्रैकेट के साथ काम करता है: [ -v name_of_var ]
meuh

7
सावधान रहें कि हैश और सरणियों के लिए, यह गलत है जब तक कि चर में कुंजी / इंडिस "0" का तत्व न हो। Namerefs के लिए, यह परीक्षण करता है कि लक्ष्य निर्धारित है या नहीं। ऐसा लगता है कि विशेष मापदंडों के लिए काम नहीं करता है $1, $-, $#...
स्टीफन Chazelas

4
यह सुविधा केवल बैश बिलिन में है testया [; इसमें उपलब्ध नहीं है /usr/bin/test। तुलना man testके साथ help test
मार्क लकाटा

@MarkLakata राइट, क्योंकि बाहरी कमांड शेल की आंतरिक स्थिति को नहीं जान सकते हैं।
क्रिस डाउन

उम हमेशा ऐसा नहीं होना चाहिए [[-v "$ name_of_var"]]?
अलेक्जेंडर मिल्स

24

निर्भर करता है कि आप क्या मतलब है मौजूद है

क्या एक वैरिएबल घोषित किया गया है, लेकिन मौजूद नहीं है ?

क्या कोई सरणी (या हैश) चर जिसे खाली सूची दी गई है, मौजूद है ?

क्या कोई ऐसा वेरिएबल वैरिएबल है जो किसी वैरिएबल की ओर इशारा करता है जो वर्तमान में असाइन नहीं है ?

आप मानते हैं $-, $#, $1चर? (POSIX नहीं है)।

बॉर्न जैसे गोले में, विहित तरीका है:

if [ -n "${var+set}" ]; then
  echo '$var was set'
fi

स्केलर चर और अन्य मापदंडों के लिए काम करता है यह बताने के लिए कि क्या चर को एक मान (खाली या नहीं, स्वचालित रूप से, पर्यावरण, assigments read, forया अन्य) से सौंपा गया है ।

ऐसे शेल के लिए जिनके पास एक कमांड typesetया declareकमांड है, जो उन वेरिएबल्स को सेट नहीं करेगा जो घोषित किए गए हैं, लेकिन इसके अलावा असाइन नहीं किए गए हैं zsh

जब तक कि ऐरे का समर्थन करने वाले गोले, इसके लिए yashऔर सेट सरणी चर के zshरूप में रिपोर्ट नहीं करेंगे, जब तक कि इंडिस 0 का तत्व सेट नहीं किया गया हो।

के लिए bash(लेकिन नहीं ksh93है और न ही zsh), प्रकार के चर के लिए साहचर्य सरणी , कि उन्हें के रूप में रिपोर्ट नहीं होगा सेट की कुंजी "0" स्थापित किया गया है उनके तत्व जब तक।

के लिए ksh93और bash, प्रकार के चर के लिए nameref , कि केवल सच लौटाता है यदि चर nameref द्वारा संदर्भित ही माना जाता है सेट

के लिए ksh, zshऔर bash, संभावित रूप से बेहतर दृष्टिकोण हो सकता है:

if ((${#var[@]})); then
  echo '$var (or the variable it references for namerefs) or any of its elements for array/hashes has been set'
fi

के लिए ksh93, zshऔर bash4.4 या इसके बाद के संस्करण, वहाँ भी है:

if typeset -p var 2> /dev/null | grep -q '^'; then
  echo '$var exists'
fi

जो उन चरों की रिपोर्ट करेगा जो निर्धारित या घोषित किए गए हैं।


1
declare -p/ अब भी typeset -pकाम करता bashहै।
कैस

1
@CAS संख्या। घोषित नहीं है, लेकिन चर सेट नहीं है। कोशिश करो bash -c 'typeset -i a; typeset -p a'और साथ तुलना करें ksh93या zsh
स्टीफन चेज़लस

+ 1 यहाँ बिंदु के लिए धन्यवाद। मेरा प्रश्न भी देखें unix.stackexchange.com/q/280893/674
टिम

@ कैस, जो बैश-4.4 के साथ बदल गया (सितंबर 2016 में रिलीज़ हुआ), मैंने इसे संपादित किया है।
स्टीफन चेज़लस

9

एसओ पर जवाब में उल्लेख किया गया है , यहां जांचने का एक तरीका है:

if [ -z ${somevar+x} ]; then echo "somevar is unset"; else echo "somevar is set to '$somevar'"; fi

जहाँ $ {somevar + x} एक पैरामीटर विस्तार है जो अशक्त का मूल्यांकन करता है यदि var unset है और स्ट्रिंग "x" को स्थानापन्न करता है।

उपयोग करना -n, जैसा कि अन्य उत्तर द्वारा सुझाया गया है, केवल यह जांच करेगा कि चर में खाली स्ट्रिंग है या नहीं। यह अपने अस्तित्व की जाँच नहीं करेगा।


2
आपको $somevarसंभालने के लिए उद्धृत करने की आवश्यकता है IFS=x। या तो वह या बोली x
मिकसर्व

1
@ माइकर्स धन्यवाद, मुझे किनारे के मामलों के बारे में सीखना पसंद है :) क्या आपका मतलब है if [ -z "${somevar+x}" ]? क्या अब भी उद्धरण की आवश्यकता होगी [[और ]]?
टॉम हेल

@TomHale - हाँ, दुर्लभ मामलों में। [ testके रूप में हमेशा की तरह इस पर भरोसा किया जाना चाहिए में आदेश दिया परीक्षण के आह्वान पर प्रस्तुत करने के लिए है कि जो आपको किसी भी कार्यक्रम कमांड लाइन से इस तरह पढ़ा जा करने के लिए कारण चाहिए लागू किया दिनचर्या आदेश पंक्ति पैरामीटर, और इसलिए हमेशा की तरह विस्तार और व्याख्याओं स्वीकार करते हैं। परीक्षण {! + "!"}
mikeserv

@ मुझे लगता है कि आपका हाँ मेरे 2 प्रश्न पर है ... क्या पहला हाँ भी है?
टॉम हेल

1
+1; ऐसा होने पर यह सबसे सरल तरीका प्रतीत होता है set -uऔर बैश संस्करण पूर्व-4.2 है।
काइल स्ट्रैंड

4

POSIXly:

! (: "${somevar?}") 2>/dev/null && echo somevar unset

या आप अपने शेल को आपके लिए संदेश दिखा सकते हैं:

(: "${somevar?}")
zsh: somevar: parameter not set

@mikeserv: हाँ, निश्चित रूप से, ऐसा करने के कई तरीके हैं। सबसे पहले, मुझे लगता है कि मैं के साथ यह दोहराया जाएगा इस । लेकिन इस सवाल में, ओपी केवल जाँच करना चाहते हैं, उन्होंने दावा नहीं किया कि वे बाहर निकलना चाहते हैं या यदि चर unset में रिपोर्ट करना चाहते हैं, तो मैं सब-चेक में आया।
congonglm

2
ठीक है, मुझे पता है, लेकिन यह ठीक है क्योंकि आपको इसे ठीक उसी तरह से करना होगा, जो यह दर्शाता है कि यह यहां परीक्षण करने का सबसे अच्छा तरीका नहीं हो सकता है - यह विफलता पर कार्रवाई है, यह किसी भी सरल साधन को संभालने की अनुमति नहीं देता है एक विफलता। आंशिक रूप से भी trapकेवल EXIT पर काम कर सकते हैं। बस इतना ही कह रहा हूँ - यह सिर्फ पास के रूप में लागू नहीं होता है / बहुत अच्छी तरह से विफल होता है। और यह मुझसे बात नहीं कर रहा है - मैंने पहले भी ऐसा किया है और मुझे समझाने के लिए इस तरह से थोड़ी टिप्पणी की। इसलिए, मैंने सोचा था कि मैं इसे आगे बढ़ाऊंगा।
अक्टूबर को सुबह

1
@ बाइक: अच्छा, ठीक है, यह अच्छी बात है। मुझे केवल आश्चर्य है, कि वाक्यविन्यास के साथ ओपी को भ्रमित कर सकता है :)
कॉंग्लम

2
if set|grep '^somevar=' >/dev/null;then
    echo "somevar exists"
else
    echo "does not exist"
fi

मैं इसके लिए कुछ हद तक अक्षम होने की कल्पना करूंगा, लेकिन यह बहुत ही सरल और shसंगत है, जिसे बस मेरी जरूरत है।
होइजुई

2
printf ${var+'$var exists!\n'}

... ऐसा नहीं होने पर कुछ भी नहीं छापेंगे। या ...

printf $"var does%${var+.}s exist%c\n" \ not !

... कोई रास्ता बताएगा।

आप अपनी स्थिति के लिए उपयुक्त प्रारूप स्ट्रिंग में गतिशील रूप से विस्तार करने के लिए परीक्षण के रिटर्न मूल्य का उपयोग कर सकते हैं:

[ "${var+1}" ]
printf $"var does%.$?0s exist%c\n" \ not !

तुम भी printfएक प्रतिस्थापन के आधार पर असफल बना सकते हैं ...

printf $"var does%${var+.}s exist%c\n%.${var+b}d" \
        \ not ! \\c >&"$((2${var+-1}))" 2>/dev/null

... जो स्टेटर $var does not exist!करने के लिए प्रिंट करता है और 0 से अलग है जब $varपरेशान होता है, लेकिन स्टडआउट $var does exist!करने के लिए प्रिंट करता है और 0 $varसेट होने पर वापस लौटता है।


1

यह सरल रेखा काम करती है (और अधिकांश पोसिक्स गोले पर काम करती है):

${var+"false"} && echo "var is unset"

या, एक लंबे रूप में लिखा गया है:

unset var

if ${var+"false"}
then
   echo "var is unset"
fi

विस्तार है:

  • यदि var का मान (यहां तक ​​कि अशक्त) है, तो गलत को बदल दिया जाता है
  • यदि संस्करण में "कोई मूल्य नहीं" है, तो "कोई मूल्य नहीं" (शून्य) को बदल दिया जाता है।

${var+"false"}विस्तार या तो "गलत" के "अशक्त" करने के लिए फैलता है।
फिर, "कुछ भी नहीं" या "गलत" निष्पादित किया जाता है, और निकास कोड सेट किया जाता है।

कमांड को test( [या [[) को कॉल करने की कोई आवश्यकता नहीं है क्योंकि एक्ज़िट वैल्यू अपने आप ही एक्सपोज़र के एक्ज़िट वैल्यू (एग्जीक्यूटिव) द्वारा सेट हो जाती है।


हाँ, श एम में zsh के कुछ पुराने संस्करणों को छोड़कर जब $IFSएफ, ए, एल, एस या ई शामिल हैं। अन्य उत्तरों की तरह, इसमें एरेज़, हैश, या अन्य प्रकार के वैरिएबल का मामला है, जिसका उल्लेख करना चाहते हैं।
स्टीफन चेज़लस

@ StéphaneChazelas मैंने लिखा है most POSIX shellsmost इसका मतलब हैIn the greatest number of instances , सभी नहीं। ... ... तो, हाँ, एक अस्पष्ट स्थिति में when $IFS contains f, a, l, s or eऔर कुछ अस्पष्ट खोल के लिए some old versions of zshयह विफल रहता है: क्या झटका है! मुझे यह मानना ​​चाहिए कि इस तरह के बग को बहुत पहले हल कर लिया गया है। ... ... क्या आप प्रस्ताव कर रहे हैं कि हमें लंबे समय से टूटे गोले के लिए कोड लिखना होगा?

@ स्टीफनचेज़ेलस भी: प्रश्न शीर्षक बहुत विशिष्ट है: बैश।

बाइनरी ज़ेबरा ???
mikeserv

0

शुद्ध खोल रास्ता:

[ "${var+1}" ] || echo "The variable has not been set"

टेस्ट स्क्रिप्ट:

#!/bin/sh
echo "Test 1, var has not yet been created"
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 2, var=1"
var=1
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 3, var="
var=
[ "${var+1}" ] || echo "The variable has not been set"

echo "Test 4, unset var"
unset var
[ "${var+1}" ] || echo "The variable has not been set"
echo "Done"

परिणाम:

Test 1, var has not yet been created
The variable has not been set
Test 2, var=1
Test 3, var=
Test 4, unset var
The variable has not been set
Done

1
जब चर स्ट्रिंग शून्य पर सेट होता है।
टॉम हेल

0

4.4.19 को हरा के साथ निम्नलिखित ने मेरे लिए काम किया। यहाँ एक पूर्ण उदाहरण है

$export MAGENTO_DB_HOST="anyvalue"

#!/bin/bash

if [ -z "$MAGENTO_DB_HOST" ]; then
    echo "Magento variable not set"
else
    echo $MAGENTO_DB_HOST
fi

-1

आप ifbash में घोषित चर के अस्तित्व की जांच करने के लिए कमांड का उपयोग नहीं कर सकते हैं, हालांकि -vविकल्प नई bash में मौजूद है, लेकिन यह पोर्टेबल नहीं है और आप इसे पुराने bashसंस्करणों में उपयोग नहीं कर सकते । क्योंकि जब आप एक चर का उपयोग कर रहे हैं यदि यह मौजूद नहीं है तो यह उसी समय पैदा होगा।

उदाहरण के लिए कल्पना कीजिए कि मैंने MYTESTवैरिएबल के लिए मान का उपयोग या असाइन नहीं किया है , लेकिन जब आप इको कमांड का उपयोग कर रहे हैं तो यह आपको कुछ नहीं दिखाता है! या यदि आप if [ -z $MYTEST ]इसका उपयोग कर रहे हैं तो यह शून्य मान लौटाया गया है! यह एक और निकास स्थिति नहीं लौटा, जो आपको बताता है कि यह चर मौजूद नहीं है!

अब आपके पास दो उपाय हैं ( -vविकल्प के बिना ):

  1. declareकमांड का उपयोग करना ।
  2. setकमांड का उपयोग करना ।

उदाहरण के लिए:

MYTEST=2
set | grep MYTEST
declare | grep MYTEST

लेकिन दुर्भाग्य से ये कमांड आपको मेमोरी में फंक्स्ड फंक्शन भी दिखाते हैं! आप declare -p | grep -q MYTEST ; echo $?क्लीनर परिणाम के लिए कमांड का उपयोग कर सकते हैं ।


-1

चर घोषित / परेशान होने की जाँच करने का कार्य

खाली सहित $array=()


@ गाइल्स के जवाब के अलावा

case " ${!foobar*} " in
  *" foobar "*) echo "foobar is declared";;
  *) echo "foobar is not declared";;
esac

- जो मुझे एक फंक्शन के भीतर एनकैप्सुलेट करने का तरीका नहीं मिला - मैं एक साधारण वर्जन जोड़ना चाहूंगा, जो कि आंशिक रूप से रिचर्ड हैनसेन के उत्तर पर आधारित है , लेकिन क्या पता खाली होने के बाद भी होता है array=():

# The first parameter needs to be the name of the variable to be checked.
# (See example below)

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}
  • यदि चर (संयुक्त राष्ट्र) सेट है, तो पहले परीक्षण करके, घोषित करने के लिए कॉल को टाला जा सकता है, यदि आवश्यक नहीं है।
  • यदि फिर भी $1एक खाली का नाम शामिल है $array=(), तो घोषित करने का आह्वान सुनिश्चित करेगा कि हमें सही परिणाम मिले
  • डिरेक्टर / देव / अशक्त के लिए बहुत अधिक डेटा पास नहीं किया जाता है क्योंकि डिक्लेयर केवल तभी कहा जाता है जब या तो वेरिएबल अनसेट हो जाता है या एक खाली एरे होता है।


निम्नलिखित कोड के साथ कार्यों का परीक्षण किया जा सकता है:

( # start a subshell to encapsulate functions/vars for easy copy-paste into the terminal
  # do not use this extra parenthesis () in a script!

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}

:;       echo -n 'a;       '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=;      echo -n 'a=;      '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a="sd";  echo -n 'a="sd";  '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=();    echo -n 'a=();    '; var_is_declared a && echo "# is declared" || echo "# is not declared"
a=("");  echo -n 'a=("");  '; var_is_declared a && echo "# is declared" || echo "# is not declared"
unset a; echo -n 'unset a; '; var_is_declared a && echo "# is declared" || echo "# is not declared"
echo ;
:;       echo -n 'a;       '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=;      echo -n 'a=;      '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a="foo"; echo -n 'a="foo"; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=();    echo -n 'a=();    '; var_is_unset a && echo "# is unset" || echo "# is not unset"
a=("");  echo -n 'a=("");  '; var_is_unset a && echo "# is unset" || echo "# is not unset"
unset a; echo -n 'unset a; '; var_is_unset a && echo "# is unset" || echo "# is not unset"
)

स्क्रिप्ट वापस आनी चाहिए

a;       # is not declared
a=;      # is declared
a="foo"; # is declared
a=();    # is declared
a=("");  # is declared
unset a; # is not declared

a;       # is unset
a=;      # is not unset
a="foo"; # is not unset
a=();    # is not unset
a=("");  # is not unset
unset a; # is unset

-1

बैश फ़ंक्शन जो स्केलर और सरणी दोनों प्रकार के लिए काम करता है :

परिभाषा

has_declare() { # check if variable is set at all
    local "$@" # inject 'name' argument in local scope
    &>/dev/null declare -p "$name" # return 0 when var is present
}

मंगलाचरण

if has_declare name="vars_name" ; then
   echo "variable present: vars_name=$vars_name"
fi
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.