मल्टीपल लॉजिकल ऑपरेटर, ((ए। बी। बी।) और सी), और "अप्रत्याशित टोकन के पास सिंटैक्स त्रुटि"


24

मैं बैश 3 के साथ काम कर रहा हूं, और मैं एक सशर्त बनाने की कोशिश कर रहा हूं। C / C ++ में, इसका मृत सरल ((A || B) && C):। बैश में, इसका मोड़ ऐसा नहीं है (मुझे लगता है कि जीआईटी लेखकों ने अन्य प्रयासों पर जाने से पहले इस कोड का योगदान दिया होगा)।

यह काम नहीं करता। ध्यान दें कि <0 or 1>एक स्ट्रिंग शाब्दिक नहीं है; इसका मतलब है 0 या 1 (आम तौर पर आता है grep -i)।

A=<0 or 1>
B=<0 or 1>
C=<0 or 1>
if [ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eqe "0" ]; then ... fi

यह परिणाम है:

line 322: syntax error near unexpected token `[['

मैंने तब कोशिश की:

A=<0 or 1>
B=<0 or 1>
C=<0 or 1>
if [ ([ "$A" -eq "0" ]) || ([ "$B" -ne "0" ]) ] && [ "$C" -eq "0" ]; then ... fi

यह परिणाम है:

line 322: syntax error near unexpected token `[['

समस्या का एक हिस्सा है खोज परिणाम तुच्छ उदाहरण हैं, न कि यौगिक स्थिति वाले अधिक जटिल उदाहरण।

मैं ((A || B) && C)बैश में एक साधारण प्रदर्शन कैसे करूं ?


मैं इसे अनियंत्रित करने और कई ब्लॉकों में समान कमांड दोहराने के लिए तैयार हूं:

A=<0 or 1>
B=<0 or 1>
C=<0 or 1>

if [ "$A" -eq "0" ] && [ "$C" -eq "0" ]; then
    ...
elif [ "$B" -ne "0" ] && [ "$C" -eq "0" ]; then
    ... 
fi

जवाबों:


42

बैश का सिंटैक्स सी-लाइक नहीं है, भले ही इसका थोड़ा हिस्सा सी से प्रेरित हो। आप बस सी कोड लिखने और काम करने की उम्मीद नहीं कर सकते।

शेल का मुख्य बिंदु कमांड चलाना है। ओपन-ब्रैकेट कमांड [एक कमांड है, जो एकल टेस्टो करता है। आप इसे testअंतिम समापन ब्रैकेट के रूप में भी लिख सकते हैं । ||और &&ऑपरेटरों खोल ऑपरेटरों रहे हैं, वे गठबंधन आदेशों , परीक्षण नहीं।

तो जब आप लिखेंगे

[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ]

जैसा कि पार्स किया गया है

[ [ "$A" -eq "0" ] ||
[ "$B" -ne "0" ] ] &&
[ "$C" -eq "0" ]

जो जैसा है वैसा है

test [ "$A" -eq "0" ||
test "$B" -ne "0" ] &&
test "$C" -eq "0"

असंतुलित कोष्ठक पर ध्यान दें? हाँ, यह अच्छा नहीं है। कोष्ठक के साथ आपके प्रयास में एक ही समस्या है: संयमी कोष्ठक।

एक साथ समूह कमांड का सिंटैक्स ब्रेसिज़ है। जिस तरह से ब्रेसिज़ को पार्स किया जाता है, उससे पहले एक पूर्ण कमांड की आवश्यकता होती है, इसलिए आपको एक नई पंक्ति या अर्धविराम के साथ ब्रेसिज़ के अंदर कमांड को समाप्त करने की आवश्यकता होगी।

if { [ "$A" -eq "0" ] || [ "$B" -ne "0" ]; } && [ "$C" -eq "0" ]; then 

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

if [[ ($A -eq 0 || $B -ne 0) && $C -eq 0 ]]; then 

यदि आपके सभी परीक्षण संख्यात्मक हैं, तो एक और तरीका है, जो आर्टिहिमेटिक अभिव्यक्तियों का परिसीमन करता है । अंकगणित के भाव बहुत ही C- जैसे वाक्य रचना के साथ पूर्णांक संगणनाएँ करते हैं।

if (((A == 0 || B != 0) && C == 0)); then 

आपको मेरी बैश ब्रैकेट प्राइमर उपयोगी लग सकती है।

[सादे श में इस्तेमाल किया जा सकता है। [[और ((बैश (और ksh और zsh) के लिए विशिष्ट हैं।

Ean यह बूलियन ऑपरेटरों के साथ कई परीक्षणों को भी जोड़ सकता है, लेकिन यह उपयोग करने के लिए बोझिल है और इसमें सूक्ष्म नुकसान हैं इसलिए मैं इसे समझाऊंगा।


धन्यवाद गिल। क्या यह बैश 4 के माध्यम से बैश 2 के लिए है? मुझे कुछ हल्के से पोर्टेबिलिटी की आवश्यकता है, लेकिन कुसलानंद ने कुछ चीजों का उल्लेख किया जो मैं नहीं कर रहा था पोर्टेबल हैं (क्या इसका मतलब है कि मैं जो कर रहा हूं वह पोर्टेबल नहीं है ?)। यहाँ, हल्के 4 का अर्थ है बैश 4 के माध्यम से बैश 4.

@jww [[ … ]]को bash 2.02 में जोड़ा गया था। ((…))2.0 में जोड़ा गया था।
गिल्स एसओ- बुराई को रोकें '

@ गिल्स - धन्यवाद। बैश 2 को शायद सबसे ज्यादा हँसी आती है। हमारे शासन के कारण, और पुराने प्लेटफार्मों को छोड़ने की अनिच्छा के कारण। बैश 2 और जीसीसी 3 हमारे फेडोरा 1 परीक्षण पर दिखाई देते हैं। हम इस अवसर पर एक पुराने मंच को जाने देंगे, लेकिन इसके कारण होने चाहिए। हम Apple, Microsoft, Mozilla, आदि को परित्याग की नीति की सदस्यता नहीं देते हैं।

@jww कृपया इस बात का पूर्वता को समझने ||और &&से परिवर्तन [करने के लिए [[और ((। समान पूर्वता में [(प्रयोग कोष्टक मूल्यांकन के क्रम को नियंत्रित करने के लिए), लेकिन && में उच्च पूर्वता है [[और ((की तुलना में ||(सी के रूप में)।

6

उपयोग करें [[:

if [[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]]; then ...

यदि आप पसंद करते हैं [, तो निम्नलिखित काम करता है:

if [ \( "$A" -eq "0" -o "$B" -ne "0" \) -a "$C" -eq "0" ]; then ...

3

-oअपने नेस्टेड के बजाय ऑपरेटर का उपयोग करें || यदि आप -aअपने अन्य कथनों में आवश्यकता हो तो प्रतिस्थापित और& का उपयोग भी कर सकते हैं ।

   EXPRESSION1 -a EXPRESSION2
          both EXPRESSION1 and EXPRESSION2 are true

   EXPRESSION1 -o EXPRESSION2
          either EXPRESSION1 or EXPRESSION2 is true


if [  "$A" -eq "0" -o "$B" -ne "0"  ] && [ "$C" -eq "0" ]; then echo success;fi

धन्यवाद। मैं भर आया -aऔर -o, लेकिन मैंने उनके साथ प्रयोग नहीं किया। स्टैक ओवरफ्लो पर किसी ने इससे बचने के लिए कहा। मैं ज्यादातर उनके साथ सहमत था क्योंकि स्क्रिप्ट का उपयोग करने के लिए कम पठनीय है।

... लेकिन अधिक पोर्टेबल।
Kusalananda

@ कुसलानंद - पोर्टेबिलिटी पर हेड-अप के लिए धन्यवाद। बश 2 के माध्यम से सिस्टम को बैश 2 के साथ सिस्टम पर चलना चाहिए। क्या [[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]]उन पर परेशानी होगी?

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