2011-08-30 8 views
10

डीबग विकल्प 'set -e -v' के साथ निम्न स्क्रिप्ट केवल वृद्धि ऑपरेटर पर विफल होती है जब चर के शून्य का पूर्व मान होता है।bash set -e और i = 0; i ++ सहमत नहीं हैं

#!/bin/bash 
set -e -v 
i=1; let i++; echo "I am still here" 
i=0; let i++; echo "I am still here" 

i=0; ((i++)); echo "I am still here" 

बैश (जीएनयू बैश, संस्करण 4.0.33 (1) -release (x86_64-सेब के darwin10) लेकिन यह भी जीएनयू बैश, संस्करण 4.2.4 (1) -release (x86_64-अज्ञात-linux-gnu))

कोई विचार?

+1

मैं कभी नहीं एक अहानिकर देख वेतन वृद्धि की उसने कल्पना भी होगा साथ '-e' सेट इस अनायास ही बातचीत पड़ा है। भाग्यशाली मुझे यह सवाल मिला। –

उत्तर

15

अपने प्रश्न का उत्तर जाने (या पारी, या ...) उपयोग करने के लिए नहीं, बल्कि रूपरेखा 'चालू बाहर निकलने से जब एक bash स्क्रिप्ट की जांच करने की कोशिश कर

i=$((i+1)) 

उपयोग करने के लिए है गैर शून्य स्थिति कोड '

set -e 

बैश के साथ मैनुअल राज्यों सेट कि -e का प्रभाव पड़ता है' यदि कोई साधारण आदेश गैर-शून्य स्थिति से निकलता है तो तत्काल बाहर निकलें। '।

दुर्भाग्य (और पारी और ...) गणना के परिणाम लौट जाने ('पिछले आर्ग 0 पर मूल्यांकन करता है, तो रिटर्न 1 करते हैं; 0 अन्यथा दिया जाता है')। तो स्थिति कोड के बजाय किसी को किसी प्रकार का रिटर्न वैल्यू मिलता है। और कभी-कभी यह वापसी मूल्य शून्य होगा और कभी-कभी गणना के आधार पर एक होगा। इसलिए सेट-आपके स्क्रिप्ट के परिणाम के आधार पर स्क्रिप्ट को बाहर निकलने का कारण बन जाएगा !!! और इसके बारे में क्या करने के लिए जब तक या तो आप यह कभी उपयोग नहीं करते हैं या के रूप में arnaud576875 जो btw अतिरिक्त सीपीयू बोझ कहते द्वारा बताया

let i++ || true 

का सहारा कोई बात नहीं है।

let ++i 

का उपयोग केवल विशिष्ट मामले है कि मैं नहीं -1 है के लिए काम करता है, देना साथ के रूप में i ++ जो जब मैं नहीं 0. इसलिए आधा समाधान है के लिए ही काम करता है।

मैं यूनिक्स प्यार हालांकि, मैं इसे किसी अन्य तरीके से नहीं होती।

+0

+1 यह उत्तर सही है। मैंने इंटरनेट और एसओ (लगभग 10) पर मिलने वाले अन्य वृद्धि विकल्पों की जांच करने के लिए एक टेस्ट स्क्रिप्ट बनाई है। यहां एक ऑनलाइन स्क्रिप्ट स्थित है: http://goo.gl/XYzrK2 – r3x

9

let के अंतिम तर्क 0 का आकलन करती है, तो चलो रिटर्न 1 (हां, तो एक गैर शून्य स्थिति):

मैनुअल से:

let arg [arg ...] 

प्रत्येक आर्ग अंकगणितीय अभिव्यक्ति है मूल्यांकन के लिए। यदि अंतिम तर्क 0 का मूल्यांकन करता है, तो 1 रिटर्न दें; 0 अन्यथा वापस आ गया है।

i++ शून्य करने के लिए मूल्यांकन करता है जब i0 है (क्योंकि यह एक के बाद वेतन वृद्धि है, तो i के पिछले मान दिया जाता है), इसलिए let रिटर्न 1, और कारण set -e, बैश मौजूद है।

let ++i   # pre-increment, if you expect `i` to never be -1 
let i++ 1  # add an expression evaluating to non-zero 
let i++ || true # call true if let returns non-zero 
+0

धन्यवाद, यह इतना adhoc आदमी है। – bliako

0

set -e पर BASH manpage को देखते हुए:

यहाँ कुछ समाधान कर रहे हैं

बाहर निकलें तुरंत अगर एक साधारण आदेश (ऊपर शेल व्याकरण) एक गैर शून्य की स्थिति के साथ बाहर निकल जाता है। [...]

तो, यदि कोई कथन गैर-शून्य निकास कोड देता है, तो खोल बाहर निकल जाएगा।

, BASH manpage पर एक नज़र ले रहा है let आदेश पर:

पिछले आर्ग का मूल्यांकन करता है, तो 0 करने के लिए, रिटर्न 1 करते हैं; 0 अन्यथा वापस आ गया है।

लेकिन प्रतीक्षा करें! i++ का उत्तर एक है और शून्य नहीं है! यह काम करना चाहिए था!

फिर से, इस सवाल का जवाब वेतन वृद्धि ऑपरेटर पर मार मैनपेज साथ है:

आईडी ++ id--: चर के बाद वेतन वृद्धि और बाद घटती

ठीक है, तो स्पष्ट नहीं है। इस खोल स्क्रिप्ट का प्रयास करें:

#!/bin/bash 
set -e -v 
i=1; let ++i; echo "I am still here" 
i=0; let ++i; echo "I am still here" 

i=0; ((++i)); echo "I am still here" 

हममम ... उम्मीद रूप में काम करता है, और सब मैंने किया था प्रत्येक पंक्ति में परिवर्तन i++++i गया था।

i++पोस्ट-वृद्धि ऑपरेटर है। इसका मतलब है कि यह वृद्धि कर देता है iके बादlet बयान एक मान देता है। चूंकि i शून्य से पहले वृद्धि की जा रही थी, let बयान एक गैर शून्य मान देता है।

हालांकि, ++iपूर्व-वृद्धि ऑपरेटर है। इसका अर्थ यह है कि बाहर निकलने की स्थिति लौटने से पहले i बढ़ता है। चूंकि i1 पर बढ़ाया गया है, इसलिए निकास स्थिति शून्य हो जाती है।

मुझे उम्मीद है कि यह समझ में आता है।

+0

यह समझ में नहीं आता है कि चलो, सेट-और और उचित मनुष्य एक साथ रहने के लिए नहीं हैं, क्योंकि कोई भी 'लिखने वाला नहीं है' सच 'जब तक एक ईमेल हस्ताक्षर के रूप में। – bliako

+0

यह तथ्य है कि 'i ++' एक वृद्धि ऑपरेटर नहीं है, लेकिन एक *** पोस्ट-वृद्धि *** ऑपरेटर जो लोगों को फेंकता है। अधिकांश लोगों को यह पता नहीं जब तक कि वे C प्रोग्रामर रहे हैं और वे इस देखा है: 'foo = पट्टी + i ++;' या 'oldfoo = foo ++' पर्याप्त बार उन्हें ब्रेन ट्यूमर देने के लिए। –

+0

ऐसा नहीं है, यह तथ्य है कि एक स्थिति कोड, जो 'सेट-ए' स्वास्थ्य की जांच के लिए उपयोग करता है, चाहे ऑपरेशन सफल हो या नहीं, गणना के परिणाम के बारे में जानकारी रिले करने के लिए उपयोग किया जाता है। डेवलपर्स ने सोचा कि यह एक सुविधा पेश करने के लिए एक बग नहीं है, एक ला: चलो i ++ || गूंज 'हाथ नहीं देखो', लेकिन अंत परिणाम यह है कि हमें डीबग करने के लिए कोड को फिर से लिखना होगा - असल में मुझे इस पर भरोसा नहीं है क्योंकि बहुत अधिक ऑपरेशन इसका पालन कर रहे हैं। और वैसे, स्थिरता के मामले के रूप में ((i = 0; i <10; i ++)) के लिए बैश होना चाहिए? चुस्त आदमी, चुपके। – bliako

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