सिंटैक्स त्रुटि पर स्क्रिप्ट के निष्पादन को कैसे नष्ट किया जाए?


15

सुरक्षित पक्ष पर होने के लिए, मैं एक स्क्रिप्ट के निष्पादन को रोकना चाहूंगा अगर यह एक सिंटैक्स त्रुटि का सामना करता है।

मेरे आश्चर्य के लिए, मैं यह हासिल नहीं कर सकता। ( set -eपर्याप्त नहीं है।) उदाहरण:

#!/bin/bash

# Do exit on any error:
set -e

readonly a=(1 2)

# A syntax error is here:

if (( "${a[#]}" == 2 )); then
    echo ok
else
    echo not ok
fi

echo status $?

echo 'Bad: has not aborted execution on syntax error!'

परिणाम (bash-3.2.39 या bash-3.2.51):

$ ./sh-on-syntax-err
./sh-on-syntax-err: line 10: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$ 

$?वाक्यविन्यास त्रुटियों को पकड़ने के लिए हम हर कथन के बाद जाँच नहीं कर सकते ।

(मुझे समझदार प्रोग्रामिंग भाषा से इस तरह के सुरक्षित व्यवहार की उम्मीद थी ... शायद इसे बग / डेवलपर्स को कोसने की इच्छा के रूप में रिपोर्ट किया जाना चाहिए)

अधिक प्रयोग

if कोई फर्क नहीं पड़ता।

हटाना if:

#!/bin/bash

set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
(( "${a[#]}" == 2 ))
echo status $?
echo 'Bad: has not aborted execution on syntax error!'

परिणाम:

$ ./sh-on-syntax-err 
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$ 

शायद, यह http://mywiki.wooledge.org/BashFAQ/105 से 2 व्यायाम से संबंधित है और इसके साथ कुछ करना है (( ))। लेकिन मुझे अभी भी एक वाक्यविन्यास त्रुटि को निष्पादित करने के लिए जारी रखना अनुचित है।

नहीं, (( ))कोई फर्क नहीं पड़ता!

यह अंकगणित परीक्षण के बिना भी बुरा व्यवहार करता है! बस एक सरल, मूल स्क्रिप्ट:

#!/bin/bash

set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
echo "${a[#]}"
echo status $?
echo 'Bad: has not aborted execution on syntax error!'

परिणाम:

$ ./sh-on-syntax-err 
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$ 

set -eपर्याप्त नहीं है क्योंकि आपके वाक्यविन्यास में त्रुटि है if। कहीं भी स्क्रिप्ट को निरस्त करना चाहिए।
जोर्डन

@jordanm ठीक है, यह एक स्पष्टीकरण हो सकता है कि क्यों set -eकाम नहीं किया है। लेकिन मेरा सवाल अभी भी समझ में आता है। क्या किसी भी सिंटैक्स त्रुटि पर गर्भपात करना संभव है?
इम्ज़ - इवान ज़खरीशेव जुले

@jordanm हटा दिया गया "अगर"; कोई विचलन नहीं करता है (मेरा प्रश्न अपडेट किया गया है)।
इम्ज़ - इवान ज़खरीयाचेव

जवाबों:


9

एक समारोह में पूरे लपेटकर चाल करने के लिए लगता है:

#!/bin/bash -e

main () {
readonly a=(1 2)
    # A syntax error is here:
    if (( "${a[#]}" == 2 )); then
        echo ok
    else
        echo not ok
    fi
    echo status $?
    echo 'Bad: has not aborted execution on syntax error!'
}

main "$@"

परिणाम:

$ ./sh-on-syntax-err 
$ ./sh-on-syntax-err line 6: #: syntax error: operand expected (error token is "#")
$ 

हालांकि मुझे कोई सुराग नहीं है - शायद कोई और समझा सकता है?


2
अब आपकी फ़ंक्शन परिभाषा पार्स और मूल्यांकन की जाती है, और यह विफल हो जाती है।
ट्रिपल

अच्छा समाधान! BTW, यह इस मामले में भी पूरे कार्यक्रम को निरस्त नहीं करता है। मैंने echo 'Bad2: has not aborted the execution after bad main!'आपके उदाहरण के लिए अंतिम के रूप में जोड़ा है , और आउटपुट है: $ LC_ALL = C ./sh-on-syntax-err ./sh-on-syntax-err: लाइन 6: #: सिंटैक्स त्रुटि: ऑपरेटिव अपेक्षित। त्रुटि टोकन "#" है) Bad2: खराब मुख्य के बाद निष्पादन को निरस्त नहीं किया है! $
imz - इवान ज़खरीयाशेव

लेकिन हमें बस एक लाइन नहीं जोड़नी चाहिए, हमें एक फ़ंक्शन के अंदर सब कुछ डालना चाहिए।
इम्ज़ - इवान ज़खरीयाशेव

@tripleee हाँ, ऐसा लगता है कि फ़ंक्शन को पार्स करने में विफल रहता है, इसलिए यह पूर्ण नहीं है, लेकिन पूरा कार्यक्रम वास्तव में इस मामले में निरस्त नहीं किया गया है (इसलिए यह निकास-पर-त्रुटि का प्रभाव नहीं है, शायद)।
इम्ज़ - इवान ज़खरीशेव

6

आप शायद के वास्तविक अर्थ के बारे में गुमराह कर रहे हैं set -ehelp setशो के आउटपुट का सावधानीपूर्वक पठन :

-e  Exit immediately if a command exits with a non-zero status.

तो आपके स्क्रिप्ट में सिंटैक्स त्रुटियों के बारे में नहीं, गैर-शून्य होने -eके आदेशों की निकास स्थिति के बारे में है।

सामान्य तौर पर, इसका उपयोग करने के लिए बुरा व्यवहार माना जाता है set -e, क्योंकि सभी त्रुटियों (यानी, कमांड से सभी गैर-शून्य रिटर्न) को स्मार्ट तरीके से स्क्रिप्ट द्वारा नियंत्रित किया जाना चाहिए (मजबूत स्क्रिप्ट पर विचार करें, न कि उन लोगों के लिए, जो आपके साथ फ़ाइल नाम दर्ज करने के बाद जंगली हो जाते हैं अंतरिक्ष या जो एक हाइपेन से शुरू होता है)।

सिंटैक्स त्रुटि के प्रकार के आधार पर, स्क्रिप्ट को भी निष्पादित नहीं किया जा सकता है। मैं बताने के लिए पार्टी में जानकार पर्याप्त नहीं कर रहा हूँ वास्तव में (यदि केवल वे वर्गीकृत किया जा सकता है) वाक्यविन्यास त्रुटियों किस वर्ग स्क्रिप्ट या नहीं इसके बारे में तुरंत गर्भपात की वजह बन सकता है। हो सकता है कि कुछ बाश गुरु इसमें शामिल हों और सब कुछ स्पष्ट करें।

मुझे केवल आशा है कि मैंने set -eवक्तव्य को स्पष्ट किया है !

आपकी इच्छा के बारे में:

मुझे एक समझदार प्रोग्रामिंग भाषा से इस तरह के सुरक्षित व्यवहार की उम्मीद थी ... शायद इसे बग / डेवलपर्स को कोसने की इच्छा के रूप में सूचित किया जाना चाहिए

जवाब निश्चित रूप से नहीं है! जैसा कि आपने देखा है ( set -eजैसा आप अपेक्षा कर रहे हैं कोई प्रतिक्रिया नहीं) वास्तव में बहुत अच्छी तरह से प्रलेखित है।


मेरा मतलब था कि इस तरह की सुविधा का अभाव एक समस्या है। मैं इस पर ध्यान केंद्रित नहीं करना चाहता था set -e- यह मेरे लक्ष्यों के थोड़े करीब है, इसीलिए इसका उल्लेख किया गया है और यहाँ इसका उपयोग किया जाता है। मेरा सवाल यह नहीं है set -e, अगर यह sytax त्रुटियों पर गर्भपात करने के लिए नहीं किया जा सकता है तो यह bash की अनिश्चितता के बारे में है। मैं इसे सिंटैक्स त्रुटियों पर हमेशा गर्भपात करने का एक तरीका ढूंढ रहा हूं।
इम्ज़ - इवान ज़खरीशेव जुले

4

आप स्क्रिप्ट की जाँच कर सकते हैं जैसे कुछ डाल कर

bash -n "$0"

स्क्रिप्ट के शीर्ष के पास - set -eकोड के किसी भी महत्वपूर्ण टुकड़े से पहले लेकिन बाद में ।

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


अति उत्कृष्ट! या, बिना set -e: bash -n "$0" || exit
डैनियल एस

0

सबसे पहले, (( ))बैश में अंकगणितीय गणनाओं के रूप में उपयोग किया जाता है, यदि में उपयोग नहीं करना है ... इसके []लिए उपयोग करें ।

दूसरा, ${a[#]}अजीब है और इसकी वजह यह है कि त्रुटियाँ दे रहा है ... #इसका कोई अर्थ नहीं है

मुझे नहीं पता कि आप इसके साथ क्या करना चाहते हैं, लेकिन मुझे लगता है कि आप खेतों की संख्या जानना चाहते हैं, इसलिए आप ${#a[*]}इसके बजाय चाहते हैं

अंत में, जब पूर्णांकों की तुलना करते हैं, तो -eqओवर की सिफारिश की जाती है ==(स्ट्रिंग्स के लिए उपयोग किया जाता है)। ==भी काम करेंगे, लेकिन -eqसिफारिश की है।

इसलिए आप यह चाहते हैं:

if [ ${#a[*]} -eq 2 ]; then 

4
यह सच नहीं है। ((कीवर्ड के साथ कीवर्ड का उपयोग करना आम है if। उदाहरण के लिए, if (( 5 * $b > 53 ))। जब तक आप बड़े गोले के साथ पोर्टेबिलिटी के लिए लक्ष्य कर रहे हैं, [[है कि आम तौर पर बेहतर से अधिक [

2
हां, मैं @ इवन से सहमत हूं - [[और ((विशेष रूप से "अगर" आदि के साथ उपयोग किए जाने वाले हल्के परीक्षणों के रूप में डिज़ाइन किए गए थे - इसके विपरीत [, वे कभी भी स्थिति का मूल्यांकन करने के लिए एक उपप्रकार नहीं रखते हैं।
इम्ज़ - इवान ज़खरीशेव

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