2010-09-29 7 views
194

मैं इस तरह अनेक शर्तों का प्रतिनिधित्व करना चाहते हैं:यदि कथन में शेल में एकाधिक स्थितियों का प्रतिनिधित्व कैसे किया जाए?

if [ ($g -eq 1 -a "$c" = "123") -o ($g -eq 2 -a "$c" = "456") ] 
then 
    echo abc; 
else 
    echo efg; 
fi 

लेकिन जब मैं स्क्रिप्ट को निष्पादित, यह

syntax error at line 15: `[' unexpected, 

जहां लाइन 15 एक दिखा रहा है पता चलता है, तो ....

इस स्थिति में क्या गलत है? मुझे लगता है कि () के साथ कुछ गलत है।

+4

आप खोल की स्थिति के बारे में पूछ नहीं कर रहे हैं लेकिन [परीक्षण] (https://de.wikipedia.org/wiki/Test_%28Unix % 2 9) स्थितियां। आपके उदाहरण में पूरी अभिव्यक्ति का मूल्यांकन 'test' ('[') द्वारा किया जाता है और शेल द्वारा नहीं। खोल केवल '[' के बाहर निकलने की स्थिति का मूल्यांकन करता है। – ceving

+0

यह भी देखें http://stackoverflow.com/questions/16203088/multiple-conditions-if-statement-bash-script – tripleee

उत्तर

252

क्लासिक तकनीक (अक्षरों से परे भागने):

if [ \("$g" -eq 1 -a "$c" = "123" \) -o \("$g" -eq 2 -a "$c" = "456" \) ] 
then echo abc 
else echo efg 
fi 

मैं दोहरे उद्धरण में $g के लिए संदर्भ संलग्न है; सामान्य रूप से यह अच्छा अभ्यास है। कड़ाई से, कोष्ठक की आवश्यकता नहीं है क्योंकि -a और -o की प्राथमिकता उनके बिना भी सही बनाती है।

ध्यान दें कि -a और -o ऑपरेटरों मुख्य रूप से पश्च संगतता के लिए, test के लिए POSIX विनिर्देशन, उर्फ ​​[ का हिस्सा हैं (क्योंकि वे 7 वें संस्करण UNIX में test का एक हिस्सा थे, उदाहरण के लिए), लेकिन वे स्पष्ट रूप से के रूप में चिह्नित कर रहे हैं POSIX द्वारा 'obsolescent'। बैश (conditional expressions देखें) -a और -o के लिए अपने वैकल्पिक ऑपरेटरों के साथ तर्क लेने के लिए क्लासिक और पॉज़िक्स अर्थों को पसंद करते हैं।


कुछ देखभाल के साथ

, तो आप और अधिक आधुनिक [[ ऑपरेटर का उपयोग, लेकिन ध्यान रखें कि बैश और कॉर्न शैल (उदाहरण के लिए) में संस्करणों समान होने की ज़रूरत नहीं हो सकता है।

for g in 1 2 3 
do 
    for c in 123 456 789 
    do 
     if [[ ("$g" -eq 1 && "$c" = "123") || ("$g" -eq 2 && "$c" = "456") ]] 
     then echo "g = $g; c = $c; true" 
     else echo "g = $g; c = $c; false" 
     fi 
    done 
done 

उदाहरण रन मैक ओएस एक्स पर बैश 3.2.57 का उपयोग कर:

g = 1; c = 123; true 
g = 1; c = 456; false 
g = 1; c = 789; false 
g = 2; c = 123; false 
g = 2; c = 456; true 
g = 2; c = 789; false 
g = 3; c = 123; false 
g = 3; c = 456; false 
g = 3; c = 789; false 

आप [[ में चर उद्धृत करने के लिए के रूप में आप [ साथ करते हैं, क्योंकि यह एक अलग आदेश नहीं है की जरूरत नहीं है उसी तरह है।


यह एक क्लासिक सवाल नहीं है?

मैंने ऐसा सोचा होगा। हालांकि, वहाँ एक और विकल्प है, अर्थात् है:

if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ] 
then echo abc 
else echo efg 
fi 

वास्तव में, अगर आप autoconf उपकरण के लिए 'पोर्टेबल खोल के दिशा निर्देशों या संबंधित संकुल, इस अंकन पढ़ा -' || 'और' && 'का उपयोग कर - है कि वे क्या सलाह देते हैं।

if [ "$g" -eq 1 ] && [ "$c" = "123" ] 
then echo abc 
elif [ "$g" -eq 2 ] && [ "$c" = "456" ] 
then echo abc 
else echo efg 
fi 

कहाँ कार्यों गूंज के रूप में के रूप में तुच्छ हैं, यह बुरा नहीं है: मैं तुम्हें के रूप में भी अब तक जा सकते हैं लगता है। जब एक्शन ब्लॉक दोहराया जाता है तो कई रेखाएं होती हैं, पुनरावृत्ति बहुत दर्दनाक होती है और पिछले संस्करणों में से एक बेहतर होता है - या आपको कार्यों को अलग-अलग then ब्लॉक में लागू किए गए फ़ंक्शन में लपेटने की आवश्यकता होती है।

+0

बहुत बहुत धन्यवाद, \\ (काम करता है। मुझे किसी अन्य वेबसाइट से उत्तर क्यों नहीं मिला? Isn यह एक क्लासिक सवाल नहीं है? – user389955

+6

यह जानना अच्छा है कि बच निकले हुए कोष्ठक काम करते हैं; एक तरफ के रूप में: इस विशेष मामले में, कोष्ठक की भी आवश्यकता नहीं होती है, क्योंकि '-ए' वास्तव में '-o' की तुलना में अधिक प्राथमिकता है (विपरीत खोल में '&&' और '||' - हालांकि, _inside_ 'bash'' [[...]] '_conditionals_,' && '_also_ की तुलना में' || 'की तुलना में अधिक प्राथमिकता है।) यदि आप' - अधिकतम मजबूती और पोर्टेबिलिटी के लिए एक 'और' -o' - जो [POSIX मैन पेज स्वयं] (http://man.cx/test) सुझाता है - आप समूह के लिए _subshells_ का भी उपयोग कर सकते हैं: 'if ([$ g -eq 1] && ["$ सी" = "123"]) || ([$ g -eq 2] && ["$ c" = "456"]) ' – mklement0

120

बैश में:

if [[ ($g == 1 && $c == 123) || ($g == 2 && $c == 456) ]] 
+7

निश्चित रूप से 'बाश' में सबसे अच्छा तरीका। एक तरफ के रूप में : इस विशेष मामले में कोष्ठक नहीं हैं यहां तक ​​कि जरूरी है, क्योंकि _inside_ '[[...]]' _conditionals_ '&&' वास्तव में '||' की तुलना में अधिक प्राथमिकता है - _outside_ ऐसी सशर्तयों के विपरीत। – mklement0

+0

क्या कोई तरीका है कि हम यह पता लगा सकते हैं कि यहां किस शर्त से मेल खाता है? क्या यह पहली संश्लेषण में था या दूसरा? – Firelord

+1

@ फ़िरलोर्ड: आपको शर्तों को 'if'/'else' कथन में अलग करने की आवश्यकता होगी और इसे दोहराने से बचने के लिए' फ़ंक्शन 'में' फिर 'और' fi' के बीच कोड रखना होगा। बहुत ही सरल मामलों में आप 'केस' कथन का उपयोग '; &' fallthrough (बैश 4 में) के साथ कर सकते हैं। –

6
$ g=3 
$ c=133 
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg" 
efg 
$ g=1 
$ c=123 
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg" 
abc 
+1

यह एक बेकार सबहेल है। इसके बजाय '{;}' का उपयोग किया जा सकता है। – phk

5

सावधान रहें, यदि आप अपने स्ट्रिंग चर में रिक्त स्थान है और आप होने की जाँच। उन्हें सही ढंग से उद्धृत करना सुनिश्चित करें।

if [ ! "${somepath}" ] || [ ! "${otherstring}" ] || [ ! "${barstring}" ] ; then 
+1

जब हम डॉलर के प्रतीक के बाद घुंघराले ब्रैकेट का उपयोग करते हैं !! –

12

/bin/bash का उपयोग करते हुए निम्नलिखित काम करेगा:

if [ "$option" = "Y" ] || [ "$option" = "y" ]; then 
    echo "Entered $option" 
fi 
0
#!/bin/bash 

current_usage=$(df -h | grep 'gfsvg-gfslv' | awk {'print $5'}) 
echo $current_usage 
critical_usage=6% 
warning_usage=3% 

if [ ${current_usage%?} -lt ${warning_usage%?} ]; then 
echo OK current usage is $current_usage 
elif [ ${current_usage%?} -ge ${warning_usage%?} ] && [ ${current_usage%?} -lt ${critical_usage%?} ]; then 
echo Warning $current_usage 
else 
echo Critical $current_usage 
fi 
+3

स्टैक ओवरफ़्लो में आपका स्वागत है! यह प्रश्न केवल * कोड के लिए नहीं बल्कि एक * स्पष्टीकरण * की तलाश में है। आपका उत्तर प्रश्नकर्ता के लिए कोई अंतर्दृष्टि प्रदान नहीं करता है, और हटाया जा सकता है। कृपया समझाए गए लक्षणों का कारण बताएं [संपादित करें]। –

संबंधित मुद्दे