क्यों एक के साथ कई आदेशों का उपयोग नहीं करता है || या && सशर्त काम?


12

यह शेल (बैश, डैश) प्रॉम्प्ट पर काम करता है:

[ -z "" ] && echo A || echo B
A

हालाँकि, मैं POSIX शेल स्क्रिप्ट लिखने की कोशिश कर रहा हूँ , यह इस तरह से शुरू होती है:

#!/bin/sh

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

readonly raw_input_string=${1}

[ -z "${raw_input_string}" ] && echo "The given argument is empty."; exit 1

और मुझे पता नहीं क्यों, लेकिन मुझे संदेश नहीं मिला :

दिया गया तर्क खाली है।

अगर मैं इस तरह से स्क्रिप्ट को कॉल करता हूं:

./test_empty_argument ""

ऐसा क्यों है?


5
देखें कि यदि कोई वैरिएबल खाली है या केवल रिक्त स्थान हैं तो मैं कैसे परीक्षण कर सकता हूं? परीक्षण के तरीकों के लिए यदि एक चर खाली है, परेशान है, या केवल खाली है। इस प्रश्न के मुद्दे का इससे कोई लेना-देना नहीं है।
ilkachachu

1
बस उपयोगif [ X”” = X”$var” ] ; then echo isempty ; fi
user2497

3
@ user2497 पिछले 20 वर्षों में जारी किसी भी शेल में उपयोग करने का कोई कारण नहीं है। यह पुराने, छोटी गाड़ी के गोले के लिए एक समाधान है।
चेपर

@chepner तो यह एक वैध समाधान नहीं है? कुछ और उपयोग किया जाना चाहिए?
user2497

6
[ "" = "$var" ]ठीक काम करेगा; एक उद्धृत रिक्त स्ट्रिंग तर्क सूची से नहीं निकाली जाएगी [। लेकिन यह आवश्यक नहीं है, क्योंकि [ -z "$var" ] यह भी ठीक काम करता है।
chepner

जवाबों:


37

ध्यान दें कि आपकी लाइन

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

यह भी ऐसा ही है

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."
exit 1

(एक निर्विवाद ;, ज्यादातर परिस्थितियों में, एक नए चरित्र द्वारा प्रतिस्थापित किया जा सकता है)

इसका मतलब यह है कि इस exit 1कथन को हमेशा निष्पादित किया जाता है, चाहे स्क्रिप्ट में कितने तर्क दिए गए हों। बदले में इसका मतलब है कि संदेश The given argument is empty.को कभी भी प्रिंट होने का मौका नहीं मिलेगा।

"शॉर्ट-सर्किट सिंटैक्स" का उपयोग करके परीक्षण के बाद एक से अधिक स्टेटमेंट को निष्पादित करने के लिए, स्टेटमेंट को समूह में रखें { ...; }। विकल्प एक उचित ifकथन का उपयोग करना है (जो, IMHO, एक स्क्रिप्ट में क्लीनर दिखता है):

if [ "$#" -ne 1 ]; then
    echo 'Invalid number of arguments, expected one.' >&2
    exit 1
fi

आपके दूसरे परीक्षण के साथ भी यही समस्या है।


के बारे में

[ -z "" ] && echo A || echo B

यह दिए गए उदाहरण के लिए काम करेगा, लेकिन सामान्य

some-test && command1 || command2

जैसा होगा वैसा नहीं होगा

if some-test; then
    command1
else
    command2
fi

इसके बजाय, यह अधिक पसंद है

if ! { some-test && command1; }; then
    command2
fi

या

if some-test && command1; then
    :
else
    command2
fi

यही है, अगर या तो परीक्षण या पहली कमांड विफल हो जाती है, तो दूसरी कमांड निष्पादित होती है, जिसका अर्थ है कि इसमें तीनों शामिल बयानों को निष्पादित करने की क्षमता है ।


18

इस:

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

नहीं है:

[ "${#}" -eq 1 ] || { echo "Invalid number of arguments, expected one."; exit 1; }

लेकिन इसके बजाय है:

{ [ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; } 
exit 1

आपकी स्क्रिप्ट इस बात से परे है कि आपने इसके लिए कितने तर्क दिए।


8

इसे और अधिक पठनीय बनाने का एक तरीका यह है कि किसी dieफ़ंक्शन (अ ला perl) को परिभाषित किया जाए :

die() {
  printf >&2 '%s\n' "$@"
  exit 1
}

# then:

[ "$#" -eq 1 ] || die "Expected one argument, got $#"

[ -n "$1" ] || die "Empty argument not supported"

आप अधिक घंटियाँ और सीटी जोड़ सकते हैं जैसे कि रंग, उपसर्ग, लाइन नंबर ... यदि आवश्यक हो।


व्यवहार में, क्या आप कभी भी अपने dieकार्य को कई तर्कों के साथ कहते हैं ? (यदि हां, तो क्या आप एक उदाहरण दे सकते हैं?) मैं लगभग समान dieफ़ंक्शन का उपयोग करता हूं , लेकिन "$*"इसके बजाय का उपयोग करें , जो कि आप क्या इरादा कर रहे हैं और अधिक हो सकता है?
jrw32982

3
इसका मूल्य "$@"यह है कि यह बहु-पंक्ति संदेशों को शाब्दिक नई सूचियों को जोड़ने की आवश्यकता के बिना अनुमति देता है।
चार्ल्स डफी

1
@ jrw32982, "$*"रिक्त स्थान के साथ आर्ग्स में शामिल होने का उपयोग करने का मतलब है कि आपको $IFSउन सभी संदर्भों में काम करने के लिए एसपीसी के लिए सेट करने की आवश्यकता है, जिसमें वे $IFSसंशोधित किए गए हैं। वैकल्पिक रूप से ksh/ के साथ zsh, आप उपयोग print -r -- "$@"या echo -E - "$@"में कर सकते हैं zsh
स्टीफन चेज़लस

@CharlesDuffy हाँ, लेकिन मैंने ऐसा कभी नहीं देखा है जो किसी dieप्रकार के फ़ंक्शन के संदर्भ में किया गया हो । मैं जो पूछ रहा हूं वह है: व्यवहार में, क्या आपने कभी किसी को die "unable to blah:" "some error"2-पंक्ति त्रुटि संदेश प्राप्त करने के उद्देश्य से लिखते देखा है ?
jrw32982

@ स्टीफनचैलेजलस गुड पॉइंट। तो (मेरे सूत्रीकरण में) यह होना चाहिए die() { IFS=" "; printf >&2 "%s\n" "$*"; exit 1; }। क्या आपने कभी व्यक्तिगत रूप से इस तरह के dieफ़ंक्शन का उपयोग printfकई तर्कों को पारित करके एक बहु-पंक्ति त्रुटि संदेश उत्पन्न करने के लिए किया है? या क्या आप कभी भी केवल एक तर्क पास करते हैं dieताकि यह केवल एक नई पंक्ति को अपने आउटपुट में जोड़े?
jrw32982

-1

मैंने अक्सर इसे एक खाली स्ट्रिंग के परीक्षण के रूप में देखा है:

if [ "x$foo" = "x" ]; then ...

होना चाहिए था "=" - निश्चित।
wef

3
यह प्रथा वस्तुतः 1970 के दशक की है। कोई कारण जो भी हवाले से प्रयोग किया जाता है और अब-अप्रचलित कार्यक्षमता जैसे सही रूप में इतने लंबे समय के किसी भी खोल कि 1992 POSIX श मानक के अनुरूप (है के साथ उपयोग करने के लिए है -a, -o, (और )derectives बताने के लिए के रूप में testएक एकल मंगलाचरण में कई आपरेशनों गठबंधन करने के लिए टाले जाते हैं; पब में मार्करों देखें oops.pengroup.org/onlinepubs/9699919799/utilities/test.html )।
चार्ल्स डफी

गैर-लाइनक्स यूनियनों को मूल 'श' के साथ '90 के दशक में भेज दिया गया था - शायद अभी भी करते हैं। उस समय मेरी नौकरी में, मुझे पोर्टेबल इंस्टॉल स्क्रिप्ट लिखना था और मैंने इस निर्माण का उपयोग किया। मैंने अभी स्थापित स्क्रिप्ट्स पर ध्यान दिया है जो कि लिनक्स के लिए NVidia जहाज हैं और वे अभी भी इस निर्माण का उपयोग करते हैं।
wef

एनवीडीआईए इसका उपयोग कर सकता है, लेकिन यह कहने के लिए नहीं है कि उनके पास ऐसा करने का कोई तकनीकी औचित्य है; वाणिज्यिक UNIX में कार्गो-पंथ विकास दुख की बात है। यहां तक ​​कि हीरलूम बॉर्न के पास बग नहीं है - इसलिए SunOS कोडबेस (जो कि गैर-पॉसिक्स को शिप करने के लिए अंतिम वाणिज्यिक UNIX है /bin/sh, और Heirloom Bourne के तत्काल पूर्ववर्ती) के पास भी नहीं था।
चार्ल्स डफी

1
मैंने टोपी नहीं पहनी है, इसलिए मैं YouTube वीडियो पोस्ट करने का वादा नहीं कर सकता, खा सकता है कि किसी को इस बग पोस्ट 1990 के साथ एक वाणिज्यिक UNIX पर प्रकाशित शेल को चालू करना चाहिए ... लेकिन अगर मैंने किया, तो यह आकर्षक होगा । :)
चार्ल्स डफी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.