असाइनमेंट एक निकास स्थिति के साथ कमांड की तरह होते हैं, सिवाय इसके जब कमांड प्रतिस्थापन है?


10

POSIX गोले में निम्नलिखित उदाहरण और उनके आउटपुट देखें:

  1. false;echo $?या false || echo 1:1
  2. false;foo="bar";echo $?या foo="bar" && echo 0:0
  3. foo=$(false);echo $?या foo=$(false) || echo 1:1
  4. foo=$(true);echo $?या foo=$(true) && echo 0:0

जैसा कि /programming/6834487/what-is-the-variable-in-shell-scripting पर सबसे अधिक वोट किए गए उत्तर द्वारा उल्लेख किया गया है :

$? का उपयोग अंतिम निष्पादित कमांड के रिटर्न मान को खोजने के लिए किया जाता है।

यह शायद इस मामले में थोड़ा भ्रामक है, तो आइए पोसिक्स परिभाषा प्राप्त करें जिसे उस थ्रेड से एक पोस्ट में भी उद्धृत किया गया है:

? सबसे हालिया पाइपलाइन (देखें पाइपलाइन) के दशमलव निकास की स्थिति का विस्तार करता है।

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

मैं देखता हूं कि यह व्यवहार एक व्यावहारिक दृष्टिकोण से कैसे समझ में आता है, लेकिन यह मुझे कुछ असामान्य लगता है कि असाइनमेंट स्वयं उस क्रम में गिना जाएगा। शायद यह स्पष्ट करने के लिए कि यह मेरे लिए अजीब क्यों है, मान लें कि असाइनमेंट एक फ़ंक्शन था:

ASSIGNMENT( VARIABLE, VALUE )

तब foo="bar"होगा

ASSIGNMENT( "foo", "bar" )

और foo=$(false)ऐसा ही कुछ होगा

ASSIGNMENT( "foo", EXECUTE( "false" ) )

इसका मतलब यह होगा कि यह पहलेEXECUTE चलता है और उसके बाद ही चलता है लेकिन अभी भी यही स्थिति है जो यहां मायने रखती है। ASSIGNMENTEXECUTE

क्या मैं अपने आकलन में सही हूं या मैं कुछ गलत / गलत समझ रहा हूं? क्या मेरे इस व्यवहार को "अजीब" के रूप में देखने के सही कारण हैं?


1
क्षमा करें, लेकिन यह मेरे लिए अस्पष्ट है कि आपको क्या अजीब लगता है।
Kusalananda

1
@ कुसलानंद शायद आपको यह बताने में मदद करें कि यह मेरे खुद से पूछने के साथ शुरू हुआ था: " false;foo="bar";echo $?आखिरी असली कमान जो हमेशा चलती थी वह हमेशा 0 क्योंfalse लौटती है ?" यह मूल रूप से है कि जब कोड से बाहर निकलने की बात आती है तो असाइनमेंट विशेष व्यवहार करते हैं। उनका एग्ज़िट कोड हमेशा 0 होता है, सिवाय इसके कि जब ऐसा कुछ ऐसा नहीं होता है, जो असाइनमेंट के राइट-हैंड साइड के हिस्से के रूप में चलता है।
phk

जवाबों:


10

असाइनमेंट के लिए निकास की स्थिति अजीब है । किसी असाइनमेंट के विफल होने का सबसे स्पष्ट तरीका यह है कि लक्ष्य चर चिह्नित किया गया है या नहीं readonly

$ err(){ echo error ; return ${1:-1} ; }
$ PS1='$? $ '
0 $ err 42
error
42 $ A=$(err 12)
12 $ if A=$(err 9) ; then echo wrong ; else E=$? ; echo "E=$E ?=$?" ; fi
E=9 ?=0
0 $ readonly A
0 $ if A=$(err 10) ; then echo wrong ; else E=$? ; echo "E=$E ?=$?" ; fi
A: is read only
1 $

ध्यान दें कि यदि कथन का सही या गलत मार्ग नहीं लिया गया है, तो असाइनमेंट विफल होने से पूरे कथन का निष्पादन रुक जाता है। POSIX मोड में bash और ksh93 और zsh एक असाइनमेंट विफल होने पर स्क्रिप्ट को निरस्त कर देगा।

इस पर POSIX मानक को उद्धृत करने के लिए :

एक कमांड नाम के बिना एक कमांड, लेकिन एक जिसमें कमांड प्रतिस्थापन शामिल है, अंतिम कमांड प्रतिस्थापन की एक निकास स्थिति है जो शेल ने प्रदर्शन किया।

यह बिल्कुल शैल व्याकरण का हिस्सा है जिसमें शामिल है

 foo=$(err 42)

जो एक simple_command(simple_command → cmd_prefix → ASSIGNMENT_WORD) से आता है । इसलिए यदि कोई असाइनमेंट सफल होता है, तो जब तक कमांड प्रतिस्थापन शामिल नहीं होता, तब तक निकास की स्थिति शून्य है, जिस स्थिति में निकास स्थिति अंतिम की स्थिति है। यदि असाइनमेंट विफल हो जाता है, तो निकास स्थिति गैर-शून्य है, लेकिन आप इसे पकड़ने में सक्षम नहीं हो सकते हैं।


1
अपने उत्तर में जोड़ने के लिए, यहां एक अलग थ्रेड से एक उत्तर दिया गया है, जहां इस पर एक नया POSIX मानक उद्धृत किया गया है, निष्कर्ष मूल रूप से एक ही है: unix.stackexchange.com/a/270831/117599
phk 1

4

तुम कहो,

... ऐसा प्रतीत होता है जैसे कि एक असाइनमेंट स्वयं एक कमांड के रूप में गिना जाता है ... एक शून्य निकास मान के साथ, लेकिन जो असाइनमेंट के दाईं ओर से पहले लागू होता है (जैसे, कमांड प्रतिस्थापन कॉल ...)

यह देखने का एक भयानक तरीका नहीं है। लेकिन यह एक मामूली निरीक्षण है। से समग्र वापसी की स्थिति

A = $ ( cmd 1 ) B = $ ( cmd 2 ) C = $ ( cmd 3 ) D = $ ( cmd 4 ) E = mc 2
से बाहर निकलने की स्थिति है । काम के बाद आती है काम 0 के लिए समग्र बाहर निकलें स्थिति निर्धारित नहीं करता है।cmd4E=D=

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

$ err() { echo "stdout $*"; echo "stderr $*" >&2; return ${1:-1}; }
$ readonly A
$ Z=$(err 41 zebra) A=$(err 42 antelope) B=$(err 43 badger)
stderr 41 zebra
stderr 42 antelope
bash: A: readonly variable
$ echo $?
1
$ printf "%s = %s\n" Z "$Z" A "$A" B "$B"
Z = stdout 41 zebra
A =
B =
$

हालाँकि A, रीडॉनली है, बैश कमांड प्रतिस्थापन को सही करने के लिए निष्पादित करता है A=- और फिर कमांड को निरस्त कर देता है क्योंकि आसानी Aसे पढ़ा जाता है। यह आगे आपकी व्याख्या का खंडन करता है कि असाइनमेंट का निकास मान असाइनमेंट के दाईं ओर से पहले लागू होता है।

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