"बैश-ई" का उपयोग करते समय मुझे एक सबशेल का आउटपुट और निकास मूल्य कैसे मिलता है?


70

निम्नलिखित कोड पर विचार करें

outer-scope.sh

#!/bin/bash
set -e
source inner-scope.sh
echo $(inner)
echo "I thought I would've died :("

inner-scope.sh

#!/bin/bash
function inner() { echo "winner"; return 1; }

outer-scope.shजब कोई कॉल inner()विफल हो जाए तो मैं बाहर निकलने की कोशिश कर रहा हूं । चूंकि $()एक उप-शेल को आमंत्रित करता है, ऐसा नहीं होता है।

इस तथ्य का संरक्षण करते हुए मुझे किसी फ़ंक्शन का आउटपुट कैसे मिलता है कि फ़ंक्शन गैर-शून्य निकास कोड के साथ बाहर निकल सकता है?

जवाबों:


102

$()बाहर निकलने की स्थिति को संरक्षित करता है; आपको बस इसे ऐसे स्टेटमेंट में उपयोग करना है, जिसकी अपनी कोई स्थिति नहीं है, जैसे कि असाइनमेंट।

उत्पादन = $ (भीतरी)

इसके बाद, $?इसमें से बाहर निकलने की स्थिति होगी inner, और आप इसके लिए सभी प्रकार के चेक का उपयोग कर सकते हैं:

output=$(inner) || exit $?
echo $output

या:

if ! output=$(inner); then
    exit $?
fi
echo $output

या:

if output=$(inner); then
    echo $output
else
    exit $?
fi

(नोट: exitतर्कों के बिना एक नंगे के बराबर है exit $?- अर्थात, यह अंतिम कमांड के बाहर निकलने की स्थिति के साथ बाहर निकलता है। मैंने केवल स्पष्टता के लिए दूसरे रूप का उपयोग किया है।)


इसके अलावा, रिकॉर्ड के लिए: sourceइस मामले में पूरी तरह से असंबंधित है। आप बस उसी परिणामों के साथ, फ़ाइल inner()में परिभाषित कर सकते हैं outer-scope.sh


ऐसा क्यों है, भले ही $? $ () की निकास स्थिति समाहित है कि स्क्रिप्ट स्वचालित रूप से बाहर नहीं निकलती है (जो -ई सेट है)? संपादित करें: कोई बात नहीं, मुझे लगता है कि आपने मेरे सवालों का जवाब दिया है, धन्यवाद!
Jabalsad

मुझे यकीन नहीं है। (मैंने उपरोक्त में से किसी का भी परीक्षण नहीं किया है।) लेकिन कुछ प्रतिबंध हैं -E, सभी को bash के मैनपेज में समझाया गया है; इसके अलावा, यदि आप के बारे में पूछ रहे हैं echo $(), तो यह हो सकता है क्योंकि उपधाराओं के निकास कोड को अनदेखा किया जाता है जब लाइन - echoकमांड - का अपना स्वयं का एक निकास कोड (आमतौर पर 0) होता है।
grawity

1
हम्म, जब मैं टाइप करता if ! $(exit 1) ; then echo $?; fiहूं, मुझे मिलता है 0। सुनिश्चित नहीं है कि ifजाने के लिए रास्ता है अगर आपको उस निकास मूल्य को संरक्षित करने की आवश्यकता है।
रॉन बुर्क

@grawity - डैश के साथ यह काम करता है? मैं कुछ कष्टप्रद Autoconf व्यवहार के आसपास काम करने की कोशिश कर रहा हूँ (अर्थात्, Autoconf रिपोर्टिंग सफलता जब Sun या IBM के संकलक टर्मिनल पर अवैध विकल्प प्रिंट करता है)।
jww 8'17

3
if ! output=$(inner); then exit $?; fi0 के रिटर्न कोड के साथ बाहर निकलेगा क्योंकि $?रिटर्न कोड के !बदले रिटर्न कोड देगा inner। आप के साथ वांछित व्यवहार प्राप्त कर सकते हैं, if output=$(inner); then : ; else exit $?; fiलेकिन यह स्पष्ट रूप से अधिक क्रिया है
एसजेएल

26

BashFAQ / 002 देखें :

यदि आप दोनों (उत्पादन, और निकास स्थिति) चाहते हैं:

output=$(command)
status=$? 

एक विशेष मामला

फ़ंक्शन स्थानीय चर के साथ एक मुश्किल मामले के बारे में ध्यान दें, निम्न कोड की तुलना करें:

f() { local    v=$(echo data; false); echo output:$v, status:$?; }
g() { local v; v=$(echo data; false); echo output:$v, status:$?; }

हम मिलेंगे:

$ f     # fooled by 'local' with inline initialization
output:data, status:0

$ g     # a good one
output:data, status:1

क्यों?

जब किसी सबमिशन के आउटपुट का उपयोग किसी localवैरिएबल को इनिशियलाइज़ करने के लिए किया जाता है , तो एग्जिट स्टेटस सब-हेल्ड के नहीं, बल्कि कमांड के होते हैं , जो सबसे अधिक होने की संभावना है ।local 0

Https://stackoverflow.com/a/4421282/537554 भी देखें


3
हालांकि यह वास्तव में सवाल का जवाब नहीं था, यह आज मेरे लिए उपयोगी है, इसलिए +1।
चारपश्चमी की रात

1
बैश कमांड के लिए निकास स्थिति हमेशा निष्पादित अंतिम कमांड की होती है। जब हम दृढ़ता से टाइप की गई भाषाओं में इतना समय बिताते हैं तो यह भूलना आसान है कि "स्थानीय" एक प्रकार का निर्दिष्ट नहीं है, लेकिन सिर्फ एक और आदेश है। यहाँ इस बिंदु को पुन: प्रसारित करने के लिए धन्यवाद, आज मेरी मदद की।
markeissler

2
वाह, मैं अभी इस सटीक मुद्दे में भाग गया और आपने इसे मंजूरी दे दी। धन्यवाद!
krb686

4
#!/bin/bash
set -e
source inner-scope.sh
foo=$(inner)
echo $foo
echo "I thought I would've died :("

जोड़कर echo, उपखंड अकेला नहीं खड़ा होता है (अलग से जाँच नहीं किया जाता है) और गर्भपात नहीं करता है। असाइनमेंट इस समस्या को कम करता है।

आप यह भी कर सकते हैं, और आउटपुट को एक फ़ाइल में पुनर्निर्देशित कर सकते हैं, बाद में इसे संसाधित करने के लिए।

tmpfile=$( mktemp )
inner > $tmpfile
cat $tmpfile
rm $tmpfile

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