कैसे निर्धारित करें कि क्या एक बैश वैरिएबल खाली है?


765

यदि बैश में एक चर खाली है ("") यह निर्धारित करने का सबसे अच्छा तरीका क्या है?

मैंने सुना है कि यह सिफारिश की जाती है कि मैं करता हूं if [ "x$variable" = "x" ]

क्या यह सही तरीका है? (कुछ और सीधा होना चाहिए)


जवाबों:


1053

यह तब तक सही होगा जब एक वेरिएबल न हो या खाली स्ट्रिंग ("") पर सेट हो।

if [ -z "$VAR" ];

14
क्या इसमें कोई चर "SET" के मान में शामिल है?
ब्रेंट

11
हां यह करता है ... "-z" परीक्षण एक शून्य-लंबाई स्ट्रिंग के लिए।
डेविड जेड

91
if [ ! -z "$VAR" ];
हारून कोपले

263
का उलटा -zहै-n if [ -n "$VAR" ];
फेलिप अल्वारेज़

19
डबल कोट्स यह सुनिश्चित करते हैं कि वेरिएबल विभाजित न हो। $varकमांड लाइन पर एक साधारण को उसके व्हाट्सएप द्वारा मापदंडों की एक सूची में विभाजित किया "$var"जाएगा , जबकि हमेशा केवल एक पैरामीटर होगा। वैरिएबल को उद्धृत करना अक्सर एक अच्छा अभ्यास होता है और आपको व्हॉट्सएप (अन्य चीजों के बीच) वाले फ़ाइलनाम पर ट्रिपिंग से रोकता है। उदाहरण: करने के बाद a="x --help", प्रयास करें cat $a- यह आपको मदद के लिए पेज देगा cat। फिर कोशिश करें cat "$a"- यह (आमतौर पर) कहेंगे cat: x --help: No such file or directory। संक्षेप में, जल्दी बोली और अक्सर बोली और आप लगभग कभी भी पछतावा नहीं करेंगे।
स्कोर_उंडर

247

बैश में, जब आप उन शेल के पोर्टेबिलिटी से चिंतित नहीं होते हैं जो इसका समर्थन नहीं करते हैं, तो आपको हमेशा डबल-ब्रैकेट सिंटैक्स का उपयोग करना चाहिए:

निम्न में से कोई भी:

if [[ -z $variable ]]
if [[ -z "$variable" ]]
if [[ ! $variable ]]
if [[ ! "$variable" ]]

बैश में, डबल वर्ग ब्रैकेट का उपयोग करके, उद्धरण आवश्यक नहीं हैं। आप एक ऐसा वैरिएबल के लिए परीक्षण सरल बना सकते हैं करता है करने के लिए एक मूल्य के होते हैं:

if [[ $variable ]]

यह वाक्य रचना ksh (कम से कम ksh93, वैसे भी) के साथ संगत है। यह शुद्ध POSIX या पुराने बॉर्न गोले जैसे श या डैश में काम नहीं करता है।

देखें मेरा उत्तर यहाँ और BashFAQ / 031 डबल और सिंगल वर्ग कोष्ठक के बीच मतभेदों के बारे में अधिक जानकारी के लिए।

आप यह देखने के लिए परीक्षण कर सकते हैं कि क्या एक चर विशेष रूप से परेशान है (जैसा कि एक रिक्त स्ट्रिंग से अलग है):

if [[ -z ${variable+x} ]]

जहाँ "x" मनमाना है।

यदि आप जानना चाहते हैं कि एक चर शून्य है, लेकिन परेशान नहीं है:

if [[ -z $variable && ${variable+x} ]]

1
यह if [[ $variable ]]मेरे लिए ठीक काम किया, और set -uअन्य प्रस्तावित समाधानों में से एक की आवश्यकता नहीं थी।
तैमू लीस्टी

3
मुझे लगता है कि यह स्वीकृत उत्तर से बेहतर है।
qed

2
जब आप ऐसा कर रहे हैं तो आपको गैर-पोर्टेबल सुविधा की सिफारिश क्यों की जा रही है?
एलिस्टेयर इरविन

19
@AlastairIrvine: मैं अपने जवाब के पहले वाक्य में पोर्टेबिलिटी का उल्लेख करता हूं, प्रश्न शीर्षक और बॉडी में "बैश" शब्द शामिल है और प्रश्न को टैग किया गया बैश है , और डबल ब्रैकेट संरचना कई मायनों में स्पष्ट लाभ प्रदान करती है। और मैं स्थिरता और स्थिरता के कारणों के लिए ब्रैकेट शैलियों को मिलाने की सलाह नहीं देता। यदि आपको shबैश के बजाय अधिकतम, न्यूनतम सामान्य भाजक पोर्टेबिलिटी की आवश्यकता है । यदि आपको उन बढ़ी हुई क्षमताओं की आवश्यकता है जो इसे प्रदान करती हैं, तो बैश का उपयोग करें और इसे पूरी तरह से उपयोग करें।
डेनिस विलियमसन

2
@BrunoBronosky: मैंने संपादन को वापस कर दिया। ;अंत में इसकी कोई आवश्यकता नहीं है । thenबिल्कुल अर्धविराम के बिना अगली पंक्ति पर हो सकता है।
डेनिस विलियमसन

230

बैश (और किसी भी POSIX- संगत शेल) में एक चर तीन राज्यों में से एक में हो सकता है:

  • सेट नहीं
  • खाली स्ट्रिंग पर सेट करें
  • एक गैर-खाली स्ट्रिंग पर सेट करें

अधिकांश समय आपको केवल यह जानने की आवश्यकता होती है कि क्या कोई वैरिएबल नॉन-खाली स्ट्रिंग पर सेट है, लेकिन कभी-कभी यह महत्वपूर्ण होता है कि वह अनसेट के बीच अंतर करे और खाली स्ट्रिंग पर सेट हो।

निम्नलिखित उदाहरण हैं कि आप विभिन्न संभावनाओं का परीक्षण कैसे कर सकते हैं, और यह बैश या किसी POSIX- संगत शेल में काम करता है:

if [ -z "${VAR}" ]; then
    echo "VAR is unset or set to the empty string"
fi
if [ -z "${VAR+set}" ]; then
    echo "VAR is unset"
fi
if [ -z "${VAR-unset}" ]; then
    echo "VAR is set to the empty string"
fi
if [ -n "${VAR}" ]; then
    echo "VAR is set to a non-empty string"
fi
if [ -n "${VAR+set}" ]; then
    echo "VAR is set, possibly to the empty string"
fi
if [ -n "${VAR-unset}" ]; then
    echo "VAR is either unset or set to a non-empty string"
fi

यहाँ एक ही बात है लेकिन काम तालिका में है:

                        +-------+-------+-----------+
                VAR is: | unset | empty | non-empty |
+-----------------------+-------+-------+-----------+
| [ -z "${VAR}" ]       | true  | true  | false     |
| [ -z "${VAR+set}" ]   | true  | false | false     |
| [ -z "${VAR-unset}" ] | false | true  | false     |
| [ -n "${VAR}" ]       | false | false | true      |
| [ -n "${VAR+set}" ]   | false | true  | true      |
| [ -n "${VAR-unset}" ] | true  | false | true      |
+-----------------------+-------+-------+-----------+

${VAR+foo}निर्माण रिक्त स्ट्रिंग पर फैलता है, तो VARसेट नहीं होने या करने के लिए fooकरता है, तो VARकुछ भी करने के लिए सेट कर दिया जाता (रिक्त स्ट्रिंग सहित)।

${VAR-foo}निर्माण के मूल्य के लिए विस्तारित VARसेट (रिक्त स्ट्रिंग पर सेट सहित) और अगर fooहै, तो सेट नहीं। यह उपयोगकर्ता-अति-योग्य चूक प्रदान करने के लिए उपयोगी है (उदाहरण के लिए, जब तक कि चर को किसी चीज़ पर सेट नहीं किया गया है , ${COLOR-red}उपयोग करने के लिए कहते हैं )।redCOLOR

[ x"${VAR}" = x ]परीक्षण के लिए अक्सर कारण की सिफारिश की जाती है कि क्या एक चर या तो परेशान है या खाली स्ट्रिंग पर सेट है क्योंकि [कमांड के कुछ कार्यान्वयन (जिसे भी जाना जाता है test) छोटी गाड़ी हैं। यदि VARऐसा कुछ करने के लिए सेट किया गया है -n, तो कुछ कार्यान्वयन गलत काम करेंगे जब दिया जाता है [ "${VAR}" = "" ]क्योंकि पहले तर्क को [गलत तरीके से -nऑपरेटर के रूप में व्याख्या की जाती है , न कि एक स्ट्रिंग के रूप में।


3
रिक्त स्ट्रिंग के लिए एक चर सेट के लिए परीक्षण का उपयोग करके भी किया जा सकता है [ -z "${VAR-set}" ]
nwellnhof

@nwellnhof: धन्यवाद! मैंने ब्रीफ़र सिंटैक्स का उपयोग करने के लिए अपना उत्तर अपडेट किया।
रिचर्ड हैनसेन

पहले और आखिरी निर्माण में क्या अंतर है? वे दोनों "VAR या तो परेशान हैं या एक गैर-रिक्त स्ट्रिंग के लिए सेट" के अनुरूप हैं।
फहीम मीठा

1
@FaheemMitha: यह आपकी गलती नहीं है - मेरा जवाब पढ़ना मुश्किल था। मैंने उम्मीद है कि उत्तर को और अधिक स्पष्ट करने के लिए मैंने एक तालिका जोड़ी।
रिचर्ड हैनसेन

2
परेशान चेक विश्वसनीय नहीं हैं। यदि उपयोगकर्ता ने कॉल किया set -uया set -o nounsetबैश में है, तो परीक्षण में केवल "bash: VAR: अनबाउंड वैरिएबल" त्रुटि होगी। अधिक विश्वसनीय अनसेट चेक के लिए stackoverflow.com/a/13864829 देखें । एक चर या अशक्त है कि क्या के लिए मेरी जाने की जाँच करें [ -z "${VAR:-}" ]। एक चर नॉन-खाली है के लिए मेरी जाँच [ "${VAR:-}" ]
केविन जिन

38

-z सबसे अच्छा तरीका है।

एक अन्य विकल्प जो मैंने उपयोग किया है वह एक चर सेट करना है, लेकिन इसे किसी अन्य चर उदाहरण द्वारा ओवरराइड किया जा सकता है

export PORT=${MY_PORT:-5432}

यदि $MY_PORTवैरिएबल खाली है, तो PORT5432 पर सेट हो जाता है, अन्यथा PORT मान पर सेट होता है MY_PORT। नोट सिंटैक्स में बृहदान्त्र और डैश शामिल हैं।


आज गलती से यह मिल गया, और यह वही था जो मैं चाहता था। धन्यवाद! मुझे set -o nounsetकुछ स्क्रिप्ट में बर्दाश्त करना होगा।
23

24

यदि आप सेट-खाली बनाम परेशान स्थिति के मामलों को अलग करने में रुचि रखते हैं, तो bash के लिए -u विकल्प देखें:

$ set -u
$ echo $BAR
bash: BAR: unbound variable
$ [ -z "$BAR" ] && echo true
bash: BAR: unbound variable
$ BAR=""
$ echo $BAR

$ [ -z "$BAR" ] && echo true
true

8

एक वैकल्पिक विकल्प जो मैंने देखा [ -z "$foo" ]है वह निम्नलिखित है, हालांकि मुझे यकीन नहीं है कि लोग इस पद्धति का उपयोग क्यों करते हैं, किसी को पता है?

[ "x${foo}" = "x" ]

वैसे भी अगर आप को सेट किए बिना चर (या तो द्वारा अनुमति न देने रहे हैं set -uया set -o nounset), तो आप उन तरीकों दोनों के साथ मुसीबत में पड़ जाएगा। इसके लिए एक सरल सुधार है:

[ -z "${foo:-}" ]

नोट: यह आपके चर को अपरिभाषित कर देगा।


3
Pubs.opengroup.org/onlinepubs/009695399/utilities/test.html-z पर विकल्प के बारे में एक टिप्पणी है । असल में, यह एक विकल्प के रूप में नहीं है । इसके बजाय, यह उन मामलों को संभालता है जहां एक मेटाचैकर के साथ शुरुआत में कुछ का विस्तार हो सकता है जो या द्वारा भ्रमित किया जाएगा। शुरुआत में एक गैर-मेटाट्रेचर को मनमाने तरीके से रखने से वह संभावना खत्म हो जाती है। -z$foo[test
जेम्स स्ने .नर

6

सवाल पूछता है , तो एक चर स्ट्रिंग खाली है जांच करने का तरीका और सबसे अच्छा जवाब पहले से ही उस के लिए दिया जाता है।
लेकिन मैं php में एक प्रोग्रामिंग पास होने के बाद यहाँ उतरा और जो मैं वास्तव में खोज रहा था वो एक bash शेल में काम करने वाले php के खाली फंक्शन की तरह एक चेक था ।
जवाबों को पढ़ने के बाद मैंने महसूस किया कि मैं बैश में ठीक से नहीं सोच रहा था, लेकिन किसी भी तरह उस क्षण में php में एक खाली समारोह मेरे bash कोड में soooo काम होता।
जैसा कि मुझे लगता है कि यह दूसरों के साथ हो सकता है, मैंने php खाली फ़ंक्शन को bash मैनुअल के

अनुसार bash में बदलने का निर्णय लिया :
एक चर को खाली माना जाता है यदि वह मौजूद नहीं है या यदि उसका मूल्य निम्न में से एक है:

  • "" (एक रिक्त स्ट्रिंग)
  • 0 (0 पूर्णांक के रूप में)
  • 0.0 (एक फ्लोट के रूप में)
  • "0" (एक स्ट्रिंग के रूप में)
  • एक खाली सरणी
  • एक वैरिएबल घोषित, लेकिन बिना मूल्य के

बेशक, अशक्त और झूठे मामलों को बाश में परिवर्तित नहीं किया जा सकता है, इसलिए उन्हें छोड़ दिया जाता है।

function empty
{
    local var="$1"

    # Return true if:
    # 1.    var is a null string ("" as empty string)
    # 2.    a non set variable is passed
    # 3.    a declared variable or array but without a value is passed
    # 4.    an empty array is passed
    if test -z "$var"
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is zero (0 as an integer or "0" as a string)
    elif [ "$var" == 0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is 0.0 (0 as a float)
    elif [ "$var" == 0.0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return
    fi

    [[ $( echo "" ) ]]
}



उपयोग का उदाहरण:

if empty "${var}"
    then
        echo "empty"
    else
        echo "not empty"
fi



डेमो:
निम्नलिखित स्निपेट:

#!/bin/bash

vars=(
    ""
    0
    0.0
    "0"
    1
    "string"
    " "
)

for (( i=0; i<${#vars[@]}; i++ ))
do
    var="${vars[$i]}"

    if empty "${var}"
        then
            what="empty"
        else
            what="not empty"
    fi
    echo "VAR \"$var\" is $what"
done

exit

आउटपुट:

VAR "" is empty
VAR "0" is empty
VAR "0.0" is empty
VAR "0" is empty
VAR "1" is not empty
VAR "string" is not empty
VAR " " is not empty

यह कहने के बाद कि इस फ़ंक्शन में शून्य पर चेक्स लॉजिक में साइड इफेक्ट्स की समस्या हो सकती है, इस फ़ंक्शन का उपयोग करने वाले किसी भी व्यक्ति को इस जोखिम का मूल्यांकन करना चाहिए और हो सकता है कि केवल पहले वाले को छोड़कर उन चेक को काटने का निर्णय लिया जाए।


फ़ंक्शन के अंदर empty- आपने [[ $( echo "1" ) ]] ; returnबस के बजाय क्यों लिखा return 1?
डोर

5

पूरे अगर-तब और -ज अनावश्यक हैं।

["$ फू"] && गूंज "फू खाली नहीं है"
["$ फू"] || गूंज "फू वास्तव में खाली है"

3
यह विफल हो जाएगा अगर foo में केवल रिक्त स्थान हों
ब्रायन

2
अगर कुछ विकल्प के रूप में व्याख्या की जाती है, तो फू कुछ पानी के छींटे से शुरू होता है। जैसे Solaris ksh , zsh और bash में कोई समस्या नहीं है, sh और / bin / test असफल होंगे
ktf

4

यह सच है जब $ FOO सेट और खाली है:

[ "${FOO+x}" = x ] && [ -z "$FOO" ]

4

व्यक्तिगत रूप से जांच के लिए अधिक स्पष्ट तरीका पसंद करें:

if [ "${VARIABLE}" == "" ]; then
  echo VARIABLE is empty
else
  echo VARIABLE is not empty
fi

1
कुछ गोले दोहरे समान संकेत को स्वीकार नहीं करते हैं।
डेनिस विलियमसन

1
सवाल बैश को लेकर था। मैं बैश का उपयोग कर रहा हूं। मेरे लिए अच्छा काम करता है। वास्तव में आप किस बारे में बोल रहे हैं?
फ़ेडिर RYKHTIK

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

एकल वर्ग कोष्ठक इस मामले में ठीक है, कृपया इसे देखें serverfault.com/questions/52034/...
लुका Borrione

4

duffbeer703 के समाधान के ऑनलाइनर विस्तार :

#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter

4

मेरा 5 सेंट: से भी छोटा सिंटैक्स है if ..., यह एक:

VALUE="${1?"Usage: $0 value"}"

यह लाइन वैल्यू सेट करेगी यदि कोई तर्क दिया गया है और एक त्रुटि के मामले में स्क्रिप्ट लाइन नंबर के साथ प्रीपेड एक त्रुटि संदेश प्रिंट करेगा (और स्क्रिप्ट निष्पादन को समाप्त कर देगा)।

एक और उदाहरण पेट-गाइड («उदाहरण 10-7» के लिए खोज) में पाया जा सकता है ।


0

एक सटीक उत्तर नहीं है, लेकिन इस चाल में भाग गया। यदि आप जिस स्ट्रिंग की तलाश कर रहे हैं वह "एक कमांड" से आती है तो आप वास्तव में कमांड को एनवी में स्टोर कर सकते हैं। चर और फिर इसे हर बार अगर स्टेटमेंट के लिए निष्पादित किया जाता है, तो किसी कोष्ठक की आवश्यकता नहीं है!

उदाहरण के लिए यह आदेश, जो निर्धारित करता है कि आप डेबियन पर हैं:

grep debian /proc/version

पूरा उदाहरण:

IS_DEBIAN="grep -i debian /proc/version"

if $IS_DEBIAN; then
  echo 'yes debian'
else
  echo 'non debian'
fi

तो यह एक अप्रत्यक्ष तरीके की तरह है (हर बार इसे फिर से चालू करना) एक खाली स्ट्रिंग की जांच करने के लिए (यह कमांड से त्रुटि प्रतिक्रिया के लिए जाँच करना होता है, लेकिन यह भी होता है कि खाली स्ट्रिंग लौटाया जाए)।

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