बैश में गैर-शून्य लंबाई स्ट्रिंग के लिए टेस्ट: [-n "$ var"] या ["$ var"]


182

मैंने बैश स्क्रिप्ट को गैर-शून्य लंबाई स्ट्रिंग के लिए दो अलग-अलग तरीकों से देखा है। अधिकांश स्क्रिप्ट -nविकल्प का उपयोग करते हैं :

#!/bin/bash
# With the -n option
if [ -n "$var" ]; then
  # Do something when var is non-zero length
fi

लेकिन एक विकल्प की वास्तव में जरूरत नहीं है:

# Without the -n option
if [ "$var" ]; then
  # Do something when var is non-zero length
fi

बेहतर तरीका कौन सा है?

इसी तरह, जो शून्य-लंबाई के परीक्षण के लिए बेहतर तरीका है:

if [ -z "$var" ]; then
  # Do something when var is zero-length
fi

या

if [ ! "$var" ]; then
  # Do something when var is zero-length
fi

जवाबों:


394

संपादित करें: यह एक और अधिक पूर्ण संस्करण है जो [(उर्फ test) और (के बीच अंतर ) दिखाता है [[

निम्न तालिका से पता चलता है कि एक चर का उद्धरण दिया गया है या नहीं, चाहे आप एकल या डबल कोष्ठक का उपयोग करते हैं और क्या चर में केवल एक स्थान होता है जो -n/-zएक चर को जांचने के लिए उपयुक्त है या नहीं इसके साथ एक परीक्षण का उपयोग करने वाली चीजें प्रभावित होती हैं ।

     | 1a    2a    3a    4a    5a    6a   | 1b    2b    3b    4b    5b    6b
     | [     ["    [-n   [-n"  [-z   [-z" | [[    [["   [[-n  [[-n" [[-z  [[-z"
-----+------------------------------------+------------------------------------
unset| false false true  false true  true | false false false false true  true
null | false false true  false true  true | false false false false true  true
space| false true  true  true  true  false| true  true  true  true  false false
zero | true  true  true  true  false false| true  true  true  true  false false
digit| true  true  true  true  false false| true  true  true  true  false false
char | true  true  true  true  false false| true  true  true  true  false false
hyphn| true  true  true  true  false false| true  true  true  true  false false
two  | -err- true  -err- true  -err- false| true  true  true  true  false false
part | -err- true  -err- true  -err- false| true  true  true  true  false false
Tstr | true  true  -err- true  -err- false| true  true  true  true  false false
Fsym | false true  -err- true  -err- false| true  true  true  true  false false
T=   | true  true  -err- true  -err- false| true  true  true  true  false false
F=   | false true  -err- true  -err- false| true  true  true  true  false false
T!=  | true  true  -err- true  -err- false| true  true  true  true  false false
F!=  | false true  -err- true  -err- false| true  true  true  true  false false
Teq  | true  true  -err- true  -err- false| true  true  true  true  false false
Feq  | false true  -err- true  -err- false| true  true  true  true  false false
Tne  | true  true  -err- true  -err- false| true  true  true  true  false false
Fne  | false true  -err- true  -err- false| true  true  true  true  false false

यदि आप जानना चाहते हैं कि एक चर गैर-शून्य लंबाई है, तो निम्न में से कोई एक कार्य करें:

  • एकल कोष्ठक (कॉलम 2a) में चर को कोट करें
  • -nएकल कोष्ठक (स्तंभ 4 ए) में चर का उपयोग और उद्धरण करें
  • डबल कोष्ठक के साथ या बिना उद्धरण के साथ या उसके बिना -n(कॉलम 1 बी - 4 बी) का उपयोग करें

कॉलम 1 ए में सूचना "दो" लेबल वाली पंक्ति पर शुरू हो रही है जो परिणाम इंगित करता है कि चर [की सामग्री का मूल्यांकन कर रहा है जैसे कि वे सशर्त अभिव्यक्ति का हिस्सा थे (परिणाम "टी" या "एफ" द्वारा निहित दावे से मेल खाता है विवरण कॉलम)। जब [[उपयोग किया जाता है (कॉलम 1 बी), चर सामग्री को एक स्ट्रिंग के रूप में देखा जाता है और मूल्यांकन नहीं किया जाता है।

कॉलम 3 ए और 5 ए में त्रुटियां इस तथ्य के कारण होती हैं कि चर मूल्य में एक स्थान शामिल है और चर अयोग्य है। फिर से, जैसा कि कॉलम 3 बी और 5 बी में दिखाया गया है, [[एक स्ट्रिंग के रूप में चर की सामग्री का मूल्यांकन करता है।

इसके विपरीत, शून्य-लंबाई के स्ट्रिंग्स के लिए परीक्षण के लिए, कॉलम 6 ए, 5 बी और 6 बी ऐसा करने के सही तरीके दिखाते हैं। यह भी ध्यान दें कि यदि विपरीत ऑपरेशन का उपयोग करने की तुलना में नकारात्मक इरादे स्पष्ट हैं, तो इनमें से किसी भी परीक्षण को नकार दिया जा सकता है। उदाहरण के लिए if ! [[ -n $var ]]:।

यदि आप उपयोग कर रहे हैं [, तो यह सुनिश्चित करने की कुंजी कि आपको अप्रत्याशित परिणाम नहीं मिल रहा है, चर को उद्धृत कर रहा है। का उपयोग करना [[, यह कोई फर्क नहीं पड़ता।

त्रुटि संदेश, जिसे दबाया जा रहा है, "यूनीरी ऑपरेटर अपेक्षित" या "बाइनरी ऑपरेटर अपेक्षित" हैं।

यह वह लिपि है जिसने ऊपर तालिका का निर्माण किया।

#!/bin/bash
# by Dennis Williamson
# 2010-10-06, revised 2010-11-10
# for http://stackoverflow.com/q/3869072
# designed to fit an 80 character terminal

dw=5    # description column width
w=6     # table column width

t () { printf '%-*s' "$w" " true"; }
f () { [[ $? == 1 ]] && printf '%-*s' "$w" " false" || printf '%-*s' "$w" " -err-"; }

o=/dev/null

echo '     | 1a    2a    3a    4a    5a    6a   | 1b    2b    3b    4b    5b    6b'
echo '     | [     ["    [-n   [-n"  [-z   [-z" | [[    [["   [[-n  [[-n" [[-z  [[-z"'
echo '-----+------------------------------------+------------------------------------'

while read -r d t
do
    printf '%-*s|' "$dw" "$d"

    case $d in
        unset) unset t  ;;
        space) t=' '    ;;
    esac

    [ $t ]        2>$o  && t || f
    [ "$t" ]            && t || f
    [ -n $t ]     2>$o  && t || f
    [ -n "$t" ]         && t || f
    [ -z $t ]     2>$o  && t || f
    [ -z "$t" ]         && t || f
    echo -n "|"
    [[ $t ]]            && t || f
    [[ "$t" ]]          && t || f
    [[ -n $t ]]         && t || f
    [[ -n "$t" ]]       && t || f
    [[ -z $t ]]         && t || f
    [[ -z "$t" ]]       && t || f
    echo

done <<'EOF'
unset
null
space
zero    0
digit   1
char    c
hyphn   -z
two     a b
part    a -a
Tstr    -n a
Fsym    -h .
T=      1 = 1
F=      1 = 2
T!=     1 != 2
F!=     1 != 1
Teq     1 -eq 1
Feq     1 -eq 2
Tne     1 -ne 2
Fne     1 -ne 1
EOF

1
धन्यवाद! मैंने "एकल कोष्ठक (कॉलम 2 ए) में चर को कोट करने" की शैली को अपनाने का फैसला किया है, आईएमओ, -एन सिर्फ शोर जोड़ता है और पठनीयता घट जाती है। इसी तरह, शून्य-लंबाई या परेशान के लिए परीक्षण के लिए, मैं उपयोग करूँगा [! [-z "$ var"] के बजाय "$ var"]।
एलनहल्से

2
तो आपके चार्ट ["बनाम [-n"(ओपी का पहला सवाल) से पता चलता है कि वे पूरी तरह से बराबर हैं, है ना?
hobs

1
@ हब्स: हां, और किसका उपयोग करना है यह इस पर निर्भर करता है कि कौन अधिक स्पष्ट है। आप यह भी देखेंगे कि बैश का उपयोग करते समय पसंद किए जाने वाले डबल-ब्रैकेट फॉर्म का उपयोग करते समय उनका समकक्ष।
अगली सूचना तक रोक दिया गया।

1
तो, अपने भयानक तालिका संक्षेप में प्रस्तुत करने, गैर-शून्य स्ट्रिंग्स के लिए परीक्षण करने के लिए स्पष्ट ( "बेहतर") तरीका है[["
hobs

22

जहां तक ​​बैश की बात है , अधिक शक्तिशाली का उपयोग करना बेहतर [[है।

सामान्य मामले

if [[ $var ]]; then   # var is set and it is not empty
if [[ ! $var ]]; then # var is not set or it is set to an empty string

उपरोक्त दो निर्माण साफ और पठनीय दिखते हैं। उन्हें ज्यादातर मामलों में पर्याप्त होना चाहिए।

ध्यान दें कि हमें चर विस्तार को उद्धृत करने की आवश्यकता नहीं है [[क्योंकि शब्द विभाजन और ग्लोबिंग का कोई खतरा नहीं है ।

को रोकने के लिए shellcheck 'के बारे में नरम शिकायतों है [[ $var ]]और [[ ! $var ]], हम इस्तेमाल कर सकते हैं -nविकल्प।

दुर्लभ मामले

हम में से एक दुर्लभ मामले में "एक खाली स्ट्रिंग पर सेट होने के बीच अंतर करने के लिए" बनाम "बिल्कुल सेट नहीं किया जा रहा है", हम इनका उपयोग कर सकते हैं:

if [[ ${var+x} ]]; then           # var is set but it could be empty
if [[ ! ${var+x} ]]; then         # var is not set
if [[ ${var+x} && ! $var ]]; then # var is set and is empty

हम -vपरीक्षण का उपयोग भी कर सकते हैं :

if [[ -v var ]]; then             # var is set but it could be empty
if [[ ! -v var ]]; then           # var is not set
if [[ -v var && ! $var ]]; then   # var is set and is empty
if [[ -v var && -z $var ]]; then  # var is set and is empty

संबंधित पोस्ट और प्रलेखन

इस विषय से संबंधित बहुत सारे पद हैं। यहाँ कुछ है:


9

यहाँ कुछ और परीक्षण हैं

सही है अगर स्ट्रिंग खाली नहीं है:

[ -n "$var" ]
[[ -n $var ]]
test -n "$var"
[ "$var" ]
[[ $var ]]
(( ${#var} ))
let ${#var}
test "$var"

सच है अगर स्ट्रिंग खाली है:

[ -z "$var" ]
[[ -z $var ]]
test -z "$var"
! [ "$var" ]
! [[ $var ]]
! (( ${#var} ))
! let ${#var}
! test "$var"

यह ओपी के सवाल का जवाब नहीं देता है कि बेहतर तरीका क्या है।
कोडोरिस्टर

0

सही उत्तर निम्नलिखित है:

if [[ -n $var ]] ; then
  blah
fi

के उपयोग को नोट करें [[...]], जो आपके लिए चर को उद्धृत करते हुए सही ढंग से संभालता है।


2
-nजब बाश में इसकी आवश्यकता नहीं है तो इसका उपयोग क्यों करें ?
कोडवर्डर

0

खाली वातावरण चर का मूल्यांकन करने का एक वैकल्पिक और शायद अधिक पारदर्शी तरीका उपयोग करना है ...

  if [ "x$ENV_VARIABLE" != "x" ] ; then
      echo 'ENV_VARIABLE contains something'
  fi

10
यह बॉर्न शेल दिनों से बहुत पुराना स्कूल है। इस पुरानी आदत को खत्म न करें। bashअपने पूर्ववर्तियों की तुलना में एक तेज उपकरण है।
tbc0

2
आपको प्री-बैश शेल के साथ भी इसकी आवश्यकता नहीं है, यदि आप सिंटैक्स से बच रहे हैं कि POSIX मानक स्पष्ट रूप से अश्लील अंकन करता है। POSIX- अनुरूप कार्यान्वयन के साथ हर शेल [ "$ENV_VARIABLE" != "" ]पर काम करेगा - न केवल बैश, बल्कि राख / डैश / ksh / आदि। test
चार्ल्स डफी

... जो कहना है, परीक्षण का उपयोग न करें -aया -oगठबंधन न करें , बल्कि उपयोग करें [ ... ] && [ ... ]या [ ... ] || [ ... ]केवल कोने के मामले जो एक परीक्षण में मनमाना चर के डेटा का उपयोग करने के लिए आवेदन कर सकते हैं, स्पष्ट रूप से बंद हैं।
चार्ल्स डफी

-2

case/esacपरीक्षण करने के लिए उपयोग करें :

case "$var" in
  "") echo "zero length";;
esac

12
कृपया नहीं। यह वह नहीं caseहै जिसका मतलब है।
tbc0

2
caseदो से अधिक विकल्प होने पर सबसे अच्छा काम करता है।
कोडोरिस्टर

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