शेल लॉजिकल ऑपरेटर्स की प्राथमिकता &&, ||


126

मैं यह समझने की कोशिश कर रहा हूं कि लॉज में लॉजिकल ऑपरेटर की प्राथमिकता कैसे काम करती है। उदाहरण के लिए, मुझे उम्मीद होगी, कि निम्नलिखित कमांड कुछ भी प्रतिध्वनित नहीं करती है।

true || echo aaa && echo bbb

हालाँकि, मेरी अपेक्षा के विपरीत, bbbमुद्रित हो जाता है।

क्या कोई कृपया बता सकता है, मैं कैसे कंपाउंडेड &&और ||ऑपरेटर्स को बैश में समझ सकता हूं ?

जवाबों:


127

कई कंप्यूटर भाषाओं में, समान वरीयता वाले ऑपरेटर बाएं-सहयोगी होते हैं । यही है, समूहीकरण संरचनाओं की अनुपस्थिति में, सबसे बाएं संचालन को पहले निष्पादित किया जाता है। बैश इस नियम का अपवाद नहीं है

यह महत्वपूर्ण है, क्योंकि बैश में, &&और ||एक ही पूर्वता है।

तो आपके उदाहरण में क्या होता है कि सबसे ||पहला ऑपरेशन ( ) पहले किया जाता है:

true || echo aaa

चूंकि trueस्पष्ट रूप से सच है, ||ऑपरेटर शॉर्ट-सर्किट और पूरे कथन को सही माना जाता है बिना मूल्यांकन की आवश्यकता के echo aaaजैसा कि आप उम्मीद करेंगे। अब यह सबसे सही संचालन करने के लिए बना हुआ है:

(...) && echo bbb

चूंकि पहले ऑपरेशन का मूल्यांकन सही था (यानी 0 से बाहर निकलने की स्थिति थी), ऐसा लगता है जैसे आप निष्पादित कर रहे हैं

true && echo bbb

इसलिए &&शॉर्ट-सर्किट नहीं होगा, यही कारण है कि आप bbbप्रतिध्वनित दिखाई देते हैं ।

आप के साथ एक ही व्यवहार मिलेगा

false && echo aaa || echo bbb

टिप्पणियों के आधार पर नोट्स

  • आपको ध्यान देना चाहिए कि बाएं-समरूपता नियम का केवल तभी पालन ​​किया जाता है जब दोनों संचालकों की एक ही पूर्वता हो। यह ऐसा नहीं है जब आप इन ऑपरेटरों को कीवर्ड जैसे संयोजन के साथ उपयोग करते हैं [[...]]या ((...))या इनका उपयोग करते हैं -oऔर -aऑपरेटर testया [कमांड के तर्क के रूप में उपयोग करते हैं । ऐसे मामलों में, ( &&या -a) OR ( ||या -o) से अधिक पूर्वता लेता है । इस बिंदु को स्पष्ट करने के लिए स्टीफन चेज़ेलस की टिप्पणी के लिए धन्यवाद।
  • ऐसा लगता है कि सी और सी जैसी भाषाओं &&में उच्च प्राथमिकता है, ||जिसके कारण शायद आपने अपने मूल निर्माण की तरह व्यवहार करने की अपेक्षा की है

    true || (echo aaa && echo bbb). 

    हालांकि, बैश के साथ ऐसा नहीं है, हालांकि, जिसमें दोनों ऑपरेटरों की एक ही मिसाल है, यही वजह है कि बैश ने लेफ्ट-एसोसिएटिविटी नियम का उपयोग करके आपकी अभिव्यक्ति को पार्स किया। इसे लाने के लिए केविन की टिप्पणी के लिए धन्यवाद।

  • ऐसे मामले भी हो सकते हैं जहां सभी 3 अभिव्यक्तियों का मूल्यांकन किया जाता है। यदि पहला कमांड एक गैर-शून्य निकास स्थिति देता है, तो ||शॉर्ट सर्किट नहीं होगा और दूसरा कमांड निष्पादित करने के लिए जाता है। यदि दूसरा कमांड एक शून्य निकास स्थिति के साथ लौटता है, तो &&शॉर्ट-सर्किट भी नहीं होगा और तीसरा कमांड निष्पादित किया जाएगा। इसे लाने के लिए इग्नासियो वाज़केज़-अब्राम्स की टिप्पणी के लिए धन्यवाद।


26
एक और अधिक भ्रम को जोड़ने के लिए एक मूत नोट: जबकि &&और ||शेल ऑपरेटरों के रूप में cmd1 && cmd2 || cmd3एक ही पूर्वता है, &&में ((...))और [[...]]पूर्ववर्तीता है ||( ((a || b && c))है ((a || (b && c))))। एक ही चला जाता है के लिए -a/ -oमें test/ [और findऔर &/ |में expr
स्टीफन चेज़लस

16
सी-जैसी भाषाओं में, &&की तुलना में उच्च प्राथमिकता है ||, इसलिए ओपी का अपेक्षित व्यवहार होगा। ऐसी भाषाओं में उपयोग किए जाने वाले अवांछित उपयोगकर्ता यह महसूस नहीं कर सकते हैं कि बैश में उनकी एक ही पूर्वता है, इसलिए यह अधिक स्पष्ट रूप से इंगित करने के लायक हो सकता है कि उनके पास बैश में एक ही पूर्वता है।
केविन

यह भी ध्यान दें कि ऐसी परिस्थितियाँ हैं जहाँ तीनों कमांडों को चलाया जा सकता है, अर्थात यदि मध्य कमान सही या गलत हो सकती है।
इग्नासियो वाज़केज़-अब्राम्स

@ केविन कृपया संपादित उत्तर की जाँच करें।
जोसेफ आर।

1
आज, मेरे लिए, "बैश ऑपरेटर पूर्वता" के लिए शीर्ष Google हिट tldp.org/LDP/abs/html/opprecedence.html है ... जो दावा करता है कि && की तुलना में उच्च पूर्वता है || फिर भी @ जोसेफ। स्पष्ट रूप से सही वास्तविक और डे जुरे है। डैश समान व्यवहार करता है और pubs.opengroup.org/onlinepubs/009695399/utilities/… में "पूर्वता" की खोज करता है , मुझे लगता है कि यह एक POSIX आवश्यकता है, इसलिए हम इस पर निर्भर हो सकते हैं। बग रिपोर्टिंग के लिए मुझे जो कुछ भी मिला वह लेखक का ईमेल पता था, जिसे निश्चित रूप से पिछले छह वर्षों में मौत के लिए स्पैम किया गया है। मैं वैसे भी कोशिश करूँगा ...
मार्टिन डोरी

62

यदि आप अपनी स्थिति पर निर्भर करने के लिए कई चीजें चाहते हैं, तो उन्हें समूह बनाएं:

true || { echo aaa && echo bbb; }

जबकि प्रिंट कुछ भी नहीं है

true && { echo aaa && echo bbb; }

दोनों तारों को प्रिंट करता है।


ऐसा होने का कारण जोसेफ द्वारा बनाया गया एक बहुत अधिक सरल उपाय है। याद रखें कि बैश क्या करता है ||और &&। यह पिछले कमांड के रिटर्न स्टेटस के बारे में है। अपने कच्चे आदेश को देखने का एक शाब्दिक तरीका है:

( true || echo aaa ) && echo bbb

पहली कमांड ( true || echo aaa) के साथ बाहर निकल रही है 0

$ true || echo aaa; echo $?
0
$ true && echo aaa; echo $?
aaa
0

$ false && echo aaa; echo $?
1
$ false || echo aaa; echo $?
aaa
0

7
+1 ओपी के इच्छित परिणाम प्राप्त करने के लिए। ध्यान दें कि आपके द्वारा रखा गया कोष्ठक (true || echo aaa) && echo bbbठीक वही है जो मैं बना रहा हूं।
जोसेफ आर।

1
दुनिया के इस पक्ष में @ ओली को देखकर अच्छा लगा।
Braiam

7
;बहुत ही अंत में अर्ध-स्तंभ पर ध्यान दें । इसके बिना, यह काम नहीं करेगा!
सर्ज स्ट्रोबंड्ट

2
मैं इस बात से परेशान था क्योंकि मैं आखिरी कमांड के बाद पीछे चल रहा था ( echo bbb;पहले उदाहरणों में)। एक बार मुझे पता चला कि मुझे याद आ रहा है, यह उत्तर वही था जो मैं खोज रहा था। मुझे जो मैं चाहता था उसे पूरा करने में मदद करने के लिए +1 करें!
डॉकटोर जे।

5
किसी (...)और के लिए भ्रम और {...}संकेतन के लिए वाचन : कमांड ग्रुपिंग मैनुअल
ANTARA

16

&&और ||ऑपरेटरों रहे हैं नहीं करता है, तो-तो-और कुछ के लिए इनलाइन प्रतिस्थापन सटीक। हालाँकि अगर सावधानी से इस्तेमाल किया जाए, तो वे एक ही चीज़ को पूरा कर सकते हैं।

एक एकल परीक्षण सीधा और अस्पष्ट है ...

[[ A == A ]]  && echo TRUE                          # TRUE
[[ A == B ]]  && echo TRUE                          # 
[[ A == A ]]  || echo FALSE                         # 
[[ A == B ]]  || echo FALSE                         # FALSE

हालांकि, कई परीक्षणों को जोड़ने का प्रयास अप्रत्याशित परिणाम प्राप्त कर सकता है ...

[[ A == A ]]  && echo TRUE   || echo FALSE          # TRUE  (as expected)
[[ A == B ]]  && echo TRUE   || echo FALSE          # FALSE (as expected)
[[ A == A ]]  || echo FALSE  && echo TRUE           # TRUE  (as expected)
[[ A == B ]]  || echo FALSE  && echo TRUE           # FALSE TRUE   (huh?)

FALSE और TRUE दोनों क्यों गूँजते हैं?

यहाँ क्या हो रहा है कि हमने महसूस नहीं किया है &&और ||ओवरलोडेड ऑपरेटर हैं जो [[ ]]हमारे और हमारे (और सशर्त निष्पादन) सूची की तुलना में सशर्त परीक्षण कोष्ठक के अंदर अलग-अलग कार्य करते हैं।

बैश मैनपेज से (संपादित) ...

सूचियाँ

एक सूची एक या एक से अधिक पाइपलाइनों का अनुक्रम है जो ऑपरेटरों में से एक द्वारा अलग किया जाता है; और, &&, या ││, और वैकल्पिक रूप से, और; या में से एक द्वारा समाप्त किया जाता है। इन सूची संचालकों में, && और list की समान पूर्वता है, उसके बाद; और, जिसकी समान पूर्वता है।

एक या एक से अधिक newlines का एक क्रम एक सूची में अर्धविराम के बजाय आदेशों को सीमांकित करने के लिए प्रकट हो सकता है।

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

AND और OR सूची क्रमशः && और, नियंत्रण ऑपरेटरों द्वारा अलग किए गए अधिक पाइपलाइनों में से एक के अनुक्रम हैं। और या OR सूचियों को बाएं समरूपता के साथ निष्पादित किया जाता है।

एक और सूची का रूप है ...
command1 && command2
Command2 निष्पादित किया जाता है यदि, और केवल अगर, कमांड 1 शून्य से बाहर निकलने की स्थिति देता है।

एक या सूची में रूप है ...
command1 ││ command2
कमांड 2 को निष्पादित किया जाता है अगर और केवल अगर कमांड 1 एक गैर-शून्य निकास स्थिति देता है।

AND और OR सूचियों की वापसी स्थिति सूची में निष्पादित अंतिम कमांड की निकास स्थिति है।

हमारे अंतिम उदाहरण पर लौटते हुए ...

[[ A == B ]]  || echo FALSE  && echo TRUE

[[ A == B ]]  is false

     ||       Does NOT mean OR! It means...
              'execute next command if last command return code(rc) was false'

 echo FALSE   The 'echo' command rc is always true
              (i.e. it successfully echoed the word "FALSE")

     &&       Execute next command if last command rc was true

 echo TRUE    Since the 'echo FALSE' rc was true, then echo "TRUE"

ठीक है। अगर यह सही है, तो अगले से अंतिम उदाहरण कुछ भी क्यों गूँजता है?

[[ A == A ]]  || echo FALSE  && echo TRUE


[[ A == A ]]  is true

     ||       execute next command if last command rc was false.

 echo FALSE   Since last rc was true, shouldn't it have stopped before this?
                Nope. Instead, it skips the 'echo FALSE', does not even try to
                execute it, and continues looking for a `&&` clause.

     &&       ... which it finds here

 echo TRUE    ... so, since `[[ A == A ]]` is true, then it echos "TRUE"

एक से अधिक &&या ||कमांड सूची में उपयोग करते समय तर्क त्रुटियों का जोखिम काफी अधिक है।

अनुशंसाएँ

एक &&या ||एक कमांड सूची में काम करता है के रूप में की उम्मीद है तो बहुत सुरक्षित है। यदि यह एक ऐसी स्थिति है जहाँ आपको किसी अन्य क्लॉज़ की आवश्यकता नहीं है, तो निम्नलिखित जैसे कुछ का पालन करने के लिए स्पष्ट हो सकता है (अंतिम 2 आदेशों को समूहित करने के लिए घुंघराले ब्रेस आवश्यक हैं) ...

[[ $1 == --help ]]  && { echo "$HELP"; exit; }

एकाधिक &&और ||ऑपरेटर, जहां अंतिम को छोड़कर प्रत्येक कमांड एक परीक्षण है (यानी कोष्ठक के अंदर [[ ]]), आमतौर पर भी सभी के रूप में सुरक्षित होते हैं, लेकिन अंतिम ऑपरेटर अपेक्षा के अनुरूप व्यवहार करता है। अंतिम ऑपरेटर अधिक thenया एक elseखंड की तरह काम करता है ।


0

मैं भी इस बात से भ्रमित हो गया लेकिन यहाँ मैं कैसे बैश के बारे में आपके कथन को पढ़ता हूँ (जैसा कि यह दायें बायें प्रतीकों को पढ़ता है):

  1. प्रतीक मिला true। एक बार कमांड के अंत तक पहुंचने के बाद इसका मूल्यांकन करने की आवश्यकता होगी। इस बिंदु पर, पता नहीं है कि क्या इसका कोई तर्क है। निष्पादन बफर में स्टोर कमांड।
  2. प्रतीक मिला ||। पिछला कमांड अब पूरा हो गया है, इसलिए इसका मूल्यांकन करें। कमांड (बफर) निष्पादित किया जा रहा है true:। मूल्यांकन का परिणाम: 0 (यानी सफलता)। स्टोर परिणाम "अंतिम मूल्यांकन" रजिस्टर में 0। अब प्रतीक पर ||ही विचार करें । यह अंतिम मूल्यांकन के गैर-शून्य होने के परिणाम पर निर्भर करता है। जाँच की "अंतिम मूल्यांकन" रजिस्टर और पाया 0. चूंकि 0 गैर-शून्य नहीं है, निम्न आदेश का मूल्यांकन करने की आवश्यकता नहीं है।
  3. प्रतीक मिला echo। इस प्रतीक को अनदेखा कर सकते हैं, क्योंकि निम्न आदेश का मूल्यांकन करने की आवश्यकता नहीं थी।
  4. प्रतीक मिला aaa। यह कमांड echo(3) का तर्क है , लेकिन चूंकि echo(3) का मूल्यांकन करने की आवश्यकता नहीं है, इसलिए इसे अनदेखा किया जा सकता है।
  5. प्रतीक मिला &&। यह अंतिम मूल्यांकन के शून्य होने के परिणाम पर निर्भर करता है। जाँच की "अंतिम मूल्यांकन" रजिस्टर और पाया 0. चूंकि 0 शून्य है, निम्नलिखित कमांड का मूल्यांकन करने की आवश्यकता है।
  6. प्रतीक मिला echo। कमांड के अंत में पहुंचने के बाद इस कमांड का मूल्यांकन करने की आवश्यकता है, क्योंकि निम्नलिखित कमांड का मूल्यांकन करने की आवश्यकता है। निष्पादन बफर में स्टोर कमांड।
  7. प्रतीक मिला bbb। यह कमांड echo(6) का तर्क है । चूंकि echoमूल्यांकन करने की आवश्यकता थी, bbbनिष्पादन बफर में जोड़ें ।
  8. लाइन के अंत तक पहुँच गया। पिछला आदेश अब पूरा हो गया है और उसका मूल्यांकन किए जाने की आवश्यकता है। कमांड (बफर) निष्पादित किया जा रहा है echo bbb:। मूल्यांकन का परिणाम: 0 (यानी सफलता)। स्टोर परिणाम "अंतिम मूल्यांकन" रजिस्टर में 0।

और निश्चित रूप से, अंतिम चरण bbbकंसोल को प्रतिध्वनित करने का कारण बनता है।

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