शेल फ़ंक्शन परिभाषा में कोष्ठकों `()` का उपयोग क्या है?


20

एक फ़ंक्शन के रूप में परिभाषित किया गया है:

do_something () {
    do it
}

मैं इसके नाम 'do_something' और घुंघराले ब्रैकेट को एक्शन कोड को समझने के लिए समझ सकता था, लेकिन इस विचार को प्राप्त करने में असमर्थ हूं कि ()यहां क्या उद्देश्य है, क्योंकि बैश स्क्रिप्ट में कोई नामांकित पैरामीटर नहीं हैं। इसे बेहतर और सीधा परिभाषित किया जा सकता है

do_something {
  do it
}

जो अपने वर्तमान सिंटैक्स के साथ संघर्ष नहीं करता है, और इससे भी अधिक घोषित करता है कि कोई नामांकित पैरामीटर नहीं हैं। यहाँ क्या उपयोग ()है?


जवाबों:


44

()वाक्यविन्यास के बिना , वाक्यविन्यास वास्तव में अस्पष्ट होगा।

कुछ होना ही हैकिसी फ़ंक्शन को परिभाषित करने के लिए अस्पष्ट सिंटैक्स , और अन्य शेल सिंटैक्स को पर्याप्त रूप से बदलने के बिना , यह होना चाहिए:

do_something {
    # one or more commands go here
}

आपने कहा कि यह "इसके वर्तमान सिंटैक्स के साथ भ्रमित नहीं होता है," लेकिन यह करता है! ध्यान दें कि जब आप उस की पहली पंक्ति को चलाने का प्रयास करते हैं तो आपको किसी भी प्रकार की सिंटैक्स त्रुटि नहीं मिलती है । आपको एक त्रुटि मिलती है, लेकिन यह सिंटैक्स के बारे में कोई त्रुटि नहीं है। दूसरी पंक्ति, }एक वाक्यविन्यास त्रुटि है, लेकिन पहली पंक्ति नहीं है। बजाय,do_something { एक कमांड चलाने का प्रयास किया जाता है do_somethingऔर {उस कमांड के तर्क के रूप में पास होता है :

$ do_something {
do_something: command not found

यदि पहले से ही कोई कमांड है do_something , तो आप इसे चला रहे हैं। यदि पहले से कोई फंक्शन है do_something, तो आप उसे कॉल कर रहे हैं । यह सामान्य रूप से महत्वपूर्ण है कि वाक्यविन्यास अस्पष्ट हो, लेकिन यह भी विशेष रूप से महत्वपूर्ण है कि किसी फ़ंक्शन को गलती से कॉल किए बिना इसे फिर से परिभाषित करना संभव है। एक फ़ंक्शन को परिभाषित करना और इसे कॉल करना एक समान नहीं दिखना चाहिए।

शेल कैसे व्यवहार करता है { और (

जैसा कि type {आपको बताएंगे, {एक शेल कीवर्ड है। यह इसे पसंद करता है[[ । यदि ऐसी स्थिति में उपयोग किया जाता है जहां यह अन्यथा एक कमांड होगी, तो {विशेष शब्दार्थ का वहन करती है। विशेष रूप से, यह कमांड ग्रुपिंग करता है। हालांकि, अन्य स्थितियों में, इसका उपयोग एक शाब्दिक {चरित्र को निरूपित करने के लिए किया जा सकता है । इसमें एक कमांड के दूसरे या बाद के शब्द के रूप में इसे पारित करने की स्थिति शामिल है।

बेशक, बैश को{ अलग-अलग तरीके से व्यवहार करने के लिए डिज़ाइन किया जा सकता था जो वर्तमान में है। हालाँकि, इसके सिंटैक्स को अब POSIX शेल के साथ संगत नहीं किया गया था, और बैश वास्तव में बॉर्न-शैली का शेल नहीं होगा और कई शेल स्क्रिप्ट चलाने में सक्षम नहीं होगा।

इसके विपरीत, (एक शेल मेटाचैकर है। यह हमेशा विशेष रूप से इलाज किया जाता है अगर यह एक आदेश में प्रकट होता है और उद्धृत नहीं है (के साथ ' ', " "या \)। इस प्रकार वाक्य रचना में कोई अस्पष्टता नहीं है:

do_something() {
    # one or more commands go here
}

इसका मतलब कुछ और नहीं हो सकता। यदि बैश में फ़ंक्शन नहीं थे, तो यह एक सिंटैक्स त्रुटि होगी, उसी कारण echo foo(bar)से सिंटैक्स त्रुटि है।

यदि आप वास्तव में ()संकेतन को नापसंद करते हैं तो आप कीवर्ड का उपयोग कर सकते हैं functionऔर इसे छोड़ सकते हैं, जैसा कि सुडोडस उल्लेख करते हैं । ध्यान दें कि यह अधिकांश अन्य बॉर्न-शैली के गोले में फ़ंक्शंस को परिभाषित करने के लिए सिंटैक्स का हिस्सा नहीं है - और कुछ में, यह समर्थित है लेकिन इस तरह से परिभाषित किए गए फ़ंक्शंस में अलग-अलग शब्दार्थ हैं - और इसलिए एक स्क्रिप्ट जो इसका उपयोग करती है वह पोर्टेबल नहीं होगी। (इस वाक्यविन्यास के अयोग्य होने का कारण यह है कि functionयह बाश में स्वयं एक खोजशब्द है जो यह दर्शाता है कि जो भी इसका अनुसरण करता है वह फ़ंक्शन परिभाषा की शुरुआत है।)

अंत में, ध्यान दें कि जब अधिकांश फ़ंक्शन परिभाषाएँ {अभ्यास में उपयोग होती हैं, तो किसी भी मिश्रित कमांड की अनुमति है। यदि आपके पास एक ऐसा कार्य है जिसका शरीर आप हमेशा एक उपधारा में चलाना चाहते हैं, तो आप इसके ( )बजाय उपयोग कर सकते हैं { }


1
उच्च स्तर पर, यह मानवीय अपेक्षाओं और पठनीयता के बारे में है। अधिकांश भाषाओं में, विशेष रूप से C, फोरट्रान, और अन्य में उस समय के दौरान जो आम तौर पर बैश स्क्रिप्टिंग भाषाओं को विकसित किया गया था, एक फ़ंक्शन / सबरूटीन में हमेशा एक तर्क सूची होती है, संभवतः खाली, जो कोष्ठक में संलग्न है। उस प्रतिमान को बदलें, और आप भाषा को समझना कठिन बनाते हैं।
jamesqf

15

()टोकन खोल दुभाषिया बताने के लिए है कि आप एक समारोह की घोषणा कर रहे हैं।

$ do_something () { echo 'do it'; } ; do_something
do it

में एक विकल्प bashहैfunction

function do_something {
 echo 'do it'
}

या एक-लाइनर के रूप में आप परीक्षण कर सकते हैं

$ bash -c "function do_something { echo 'do it'; } ; do_something"
do it

2
functionकीवर्ड एक पूर्व POSIX ksh-वाद है कि पश्च संगतता के लिए पार्टी का समर्थन करता है; हालाँकि, बैश इसे बुरी तरह से समर्थन करता है (वैरिएबल फ़ंक्शन-स्थानीय डिफ़ॉल्ट नहीं बना रहा, जैसा कि पुराने ksh ने उस रूप में घोषित कार्यों में किया था)। नतीजतन, यह नए कोड के लिए आदर्श नहीं है। देखें wiki.bash-hackers.org/scripting/obsolete
चार्ल्स डफी

@CharlesDuffy, इस स्पष्टीकरण के लिए धन्यवाद :-)
sudodus

1
@CharlesDuffy क्या आप कह रहे हैं कि ksh और bash कुछ सिंटैक्स स्वीकार करते हैं जो ksh में एक वैरिएबल लोकल बनाता है, लेकिन bash में ग्लोबल है? यह सही नहीं लगता। मेरी समझ, आंशिक रूप से उस पोस्ट और जाँच (ksh93 में) के आधार पर, यह है कि ksh बैश की तुलना में कम स्थितियों में वैरिएबल बनाता है , कभी अधिक नहीं। बश में, typesetबिना -gकिसी फ़ंक्शन के हमेशा एक स्थानीय चर घोषित करता है। functionकीवर्ड के साथ , बैश और ksh स्कोप एक ही तरह से चरते हैं , क्या वे नहीं करते हैं?
एलियाह कगन

@ एलियाकगन मुझे लगता है कि चार्ल्स ने यहां गिल के जवाब में किस बात का जिक्र किया है
सर्गी कोलोडियाज़नी

9

कितना एक-सच्चा-ब्रेस-स्टाइल !

अन्य पर विचार करें, पूरी तरह से ठीक ब्रेस स्टाइल:

foo
{
  ...
}
foo
  {
    ...
  }
foo
  while ...; do ...; done # Look, ma! No braces!
foo
( ... ) # Look, ma! No braces and a subshell to boot!

शेल यह कैसे बता सकता है कि वे फ़ंक्शन परिभाषाएँ हैं और केवल fooकमांड सूचियों के बाद एक कमांड नहीं है ? इन सभी मामलों में, कीवर्ड ()या functionकीवर्ड की तरह एक अतिरिक्त वितरण कारक आवश्यक है।


दूसरे विचार पर, यह वास्तव में ओटीबीएस नहीं है, क्योंकि एक जगह जहां ओटीबीएस एक नई लाइन पर ब्रेसिज़ की अनुमति देता है, फ़ंक्शन परिभाषाओं के लिए है।
मूरू

3
मुझे लगता है कि एक तर्क दिया जाना चाहिए कि आप इसे ओटीबीएस के रूप में चिह्नित करने के लिए सही थे, क्योंकि सी और सी ++ में कार्यों के विपरीत, बॉर्न-शैली शेल स्क्रिप्ट में एक फ़ंक्शन परिभाषा सीधे दूसरे फ़ंक्शन परिभाषा के शरीर में निहित हो सकती है और इसलिए यकीनन प्रतिष्ठित होने के लायक नहीं है। (या शायद यह जावा प्रोग्रामिंग में लोकप्रिय शैली है, जहां ओटीबीएस के बजाय तरीकों को एक ही लाइन पर उनके शुरुआती ब्रेस मिलते हैं।) किसी भी तरह, आप एक उत्कृष्ट बिंदु बनाते हैं कि कैसे सिंटैक्स को काम करने के लिए ब्रेस प्लेसमेंट पर तंग बाधाओं को लागू करना होगा। बिना ()किसी चीज के या बिना किसी चीज के।
एलियाह कगन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.