बैश में, कब उर्फ, कब स्क्रिप्ट, और कब एक फ़ंक्शन लिखना है?


360

यह प्रश्न पूछने के लिए मुझे लगभग 10 साल के लिनक्स उपयोग की जानकारी मिली है। यह सभी परीक्षण और त्रुटि और यादृच्छिक देर रात इंटरनेट सर्फिंग था।

लेकिन इसके लिए लोगों को 10 साल चाहिए। अगर मैं अभी लिनक्स से शुरुआत कर रहा था, तो मैं जानना चाहता हूं: कब उर्फ, कब स्क्रिप्ट के लिए, और कब एक फंक्शन लिखना है?

जहाँ उपनामों का संबंध है, मैं बहुत ही सरल ऑपरेशन के लिए उपनामों का उपयोग करता हूं जो तर्क नहीं लेते हैं।

alias houston='cd /home/username/.scripts/'

यह स्पष्ट प्रतीत होता है। लेकिन कुछ लोग ऐसा करते हैं:

alias command="bash bashscriptname"

(और इसे .bashrcफ़ाइल में जोड़ें )

क्या ऐसा करने का कोई अच्छा कारण है? मैं वास्तव में कठिन प्रयास कर रहा हूं, लेकिन मैं वास्तव में किसी भी परिस्थिति के बारे में नहीं सोच सकता हूं जिसमें मैं ऐसा करना चाहता हूं। इसलिए, अगर कोई बढ़त का मामला है जहां इससे फर्क पड़ेगा, तो कृपया नीचे जवाब दें।

क्योंकि यही वह जगह है जहाँ मैं अपने PATH में कुछ डालूँगा और chmod +xयह, जो कि लिनक्स परीक्षण और त्रुटि के वर्षों बाद आया है।

जो मुझे अगले विषय पर लाता है। उदाहरण के लिए, मैंने .scripts/अपने पीएटीएच में होम डिरेक्टरी में एक हिडन फोल्डर ( ) को केवल मेरे लिए एक लाइन जोड़कर .bashrc( PATH=$PATH:/home/username/.scripts/) जोड़ा है , इसलिए वहाँ कुछ भी स्वचालित रूप से स्वतः पूर्ण हो जाता है।

अगर मुझे जरूरत पड़ी।

मुझे वास्तव में इसकी आवश्यकता नहीं है, हालांकि, क्या मैं? मैं केवल उन भाषाओं के लिए उपयोग करूंगा जो शेल नहीं हैं, जैसे पायथन।

यदि यह शेल है, तो मैं बहुत ही अंदर एक फ़ंक्शन लिख सकता हूं .bashrc:

funcname () {
  somecommand -someARGS "$@"
}

जैसा कि मैंने कहा, मुझे परीक्षण और त्रुटि के माध्यम से इसका बहुत पता चला। और मैंने केवल उन कार्यों की सुंदरता को देखा है जब मेरे कंप्यूटर की मृत्यु हो गई थी और मुझे अपने आसपास के लोगों के कंप्यूटर का उपयोग करने के लिए मजबूर किया गया था जब वे उनका उपयोग नहीं कर रहे थे।

कंप्यूटर से कंप्यूटर पर स्क्रिप्ट की एक पूरी निर्देशिका को स्थानांतरित करने के बजाय, मैंने अपने सभी के साथ .Bashrc की जगह बस समाप्त कर दिया, क्योंकि उन्होंने कभी भी एक भी संशोधन नहीं किया था।

लेकिन क्या मुझे कुछ याद आया?

तो, क्या आप एक शुरुआत लिनक्स उपयोगकर्ता को बताएंगे कि कब उर्फ, कब स्क्रिप्ट, और कब एक फ़ंक्शन लिखना है?

यदि यह स्पष्ट नहीं है, तो मैं उन लोगों को मान रहा हूं जो इसका उत्तर देते हैं, तीनों विकल्पों का उपयोग करेंगे। यदि आप केवल उपनाम का उपयोग करते हैं, या केवल स्क्रिप्ट का उपयोग करते हैं, या केवल फ़ंक्शन का उपयोग करते हैं- या यदि आप केवल उपनाम और स्क्रिप्ट या उपनाम और फ़ंक्शन या स्क्रिप्ट और फ़ंक्शन का उपयोग करते हैं - तो यह प्रश्न वास्तव में आपके लिए लक्षित नहीं है।



10
+1 को स्पष्ट रूप से {उपनाम, स्क्रिप्ट, फ़ंक्शन} के सभी सबसेट के लिए, जिस पर यह प्रश्न लक्षित नहीं होता है। बच्चे के विश्वास के लिए +1 कि यह आपके लिए शून्य सबसेट को छोड़ना ठीक है।
थॉमस एल होलाडे

1
हालाँकि यह सवाल विशेष रूप से बैश के बारे में पूछा गया था, ध्यान दें कि पुराने बॉर्न गोले में 'उर्फ' था, लेकिन कार्य नहीं। यदि आप संगतता के बारे में चिंतित हैं तो इससे फर्क पड़ सकता है।
एंडी बीआर

अगर .bashrc वास्तव में इसके लिए सबसे अच्छी जगह है, या कम से कम एक ठोस जगह है? लिनक्स में एक ही काम करने के लिए बहुत सारे तरीके हैं, जिनकी मैं सराहना करता हूं, हालांकि, सभी चीजें समान हैं, मैं चीजों को सबसे सामान्य तरीके से करना पसंद करता हूं।
किट

जवाबों:


242

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

# Make ls output in color by default.
alias ls="ls --color=auto"
# make mv ask before overwriting a file by default
alias mv="mv -i"

एक फ़ंक्शन का उपयोग तब किया जाना चाहिए जब आपको उपनाम से कुछ अधिक जटिल करने की आवश्यकता होती है, लेकिन यह अपने आप ही उपयोग में नहीं होगा। उदाहरण के लिए, एक प्रश्न पर यह उत्तर लें कि मैंने grepएक पाइपलाइन में क्या है, इस पर निर्भर करते हुए डिफ़ॉल्ट व्यवहार को बदलने के बारे में पूछा :

grep() { 
    if [[ -t 1 ]]; then 
        command grep -n "$@"
    else 
        command grep "$@"
    fi
}

यह एक फ़ंक्शन का एक आदर्श उदाहरण है क्योंकि यह एक उपनाम के लिए बहुत जटिल है (एक शर्त के आधार पर अलग-अलग चूक की आवश्यकता होती है), लेकिन यह ऐसा कुछ नहीं है जिसकी आपको गैर-इंटरैक्टिव स्क्रिप्ट में आवश्यकता होगी।

यदि आपको बहुत अधिक कार्य या फ़ंक्शन बहुत बड़े मिलते हैं, तो उन्हें एक छिपी निर्देशिका में अलग-अलग फ़ाइलों में डालें, और उन्हें अपने स्रोत में रखें ~/.bashrc:

if [ -d ~/.bash_functions ]; then
    for file in ~/.bash_functions/*; do
        . "$file"
    done
fi

एक स्क्रिप्ट को अपने दम पर खड़ा होना चाहिए। इसका मूल्य उस चीज़ के रूप में होना चाहिए जिसका पुन: उपयोग किया जा सकता है, या एक से अधिक उद्देश्यों के लिए उपयोग किया जा सकता है।


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

260

अन्य उत्तर व्यक्तिगत स्वाद के आधार पर कुछ नरम सामान्य दिशानिर्देश प्रदान करते हैं, लेकिन कई प्रासंगिक तथ्यों को अनदेखा करते हैं, जिन्हें स्क्रिप्ट, फ़ंक्शन या उपनाम के बीच निर्णय लेते समय विचार करना चाहिए।

उपनाम और कार्य ¹

  • उपनाम और कार्यों की पूरी सामग्री शेल की मेमोरी में संग्रहीत की जाती है।
  • इसका एक प्राकृतिक परिणाम उपनाम है और फ़ंक्शंस का उपयोग केवल वर्तमान शेल द्वारा किया जा सकता है, न कि किसी अन्य प्रोग्राम द्वारा, जो आप शेल से पाठ संपादकों, स्क्रिप्ट्स, या यहां तक ​​कि एक ही शेल के बच्चे के उदाहरणों के लिए आमंत्रित कर सकते हैं।
  • उपनाम और कार्यों को मौजूदा शेल द्वारा निष्पादित किया जाता है, अर्थात वे शेल के वर्तमान वातावरण को प्रभावित करते हैं और प्रभावित करते हैं। अलियास या फ़ंक्शन को चलाने के लिए कोई अलग प्रक्रिया आवश्यक नहीं है।

स्क्रिप्ट

  • गोले स्मृति में स्क्रिप्ट नहीं रखते हैं। इसके बजाय, स्क्रिप्ट को उन फ़ाइलों से पढ़ा जाता है, जहां उन्हें हर बार संग्रहीत किया जाता है, जिनकी उन्हें आवश्यकता होती है। यदि स्क्रिप्ट को $PATHखोज के माध्यम से पाया जाता है , तो भविष्य के $PATHलुक-अप पर समय बचाने के लिए कई गोले स्मृति में अपने पथ नाम का एक हैश रखते हैं , लेकिन उपयोग में न होने पर यह स्क्रिप्ट की मेमोरी पदचिह्न की सीमा है।
  • लिपियों को कार्यों और उपनामों की तुलना में अधिक तरीकों से लागू किया जा सकता है। उन्हें एक दुभाषिया के तर्क के रूप में पारित किया जा सकता है, जैसे sh script, या सीधे निष्पादन योग्य के रूप में आमंत्रित किया जाता है, इस स्थिति में शेबंग लाइन (जैसे #!/bin/sh) में दुभाषिया को इसे चलाने के लिए आमंत्रित किया जाता है। दोनों ही मामलों में, स्क्रिप्ट को एक अलग दुभाषिया प्रक्रिया द्वारा चलाया जाता है, अपने स्वयं के वातावरण से अलग है जो आपके शेल से अलग है, जिसका पर्यावरण किसी भी तरह से स्क्रिप्ट को प्रभावित नहीं कर सकता है। वास्तव में, दुभाषिया शेल को आह्वान करने वाले शेल से मेल खाना भी नहीं है। क्योंकि इस तरह से ली गई स्क्रिप्ट किसी भी सामान्य निष्पादन योग्य की तरह व्यवहार करती दिखाई देती हैं, उनका उपयोग किसी भी कार्यक्रम द्वारा किया जा सकता है।

    अंत में, एक स्क्रिप्ट को पढ़ा जा सकता है और वर्तमान शेल के साथ .या कुछ गोले में चलाया जा सकता है source। इस मामले में, स्क्रिप्ट एक फ़ंक्शन की तरह व्यवहार करती है जिसे स्मृति में लगातार रखे जाने के बजाय ऑन-डिमांड पढ़ा जाता है।

आवेदन

उपरोक्त को देखते हुए, हम कुछ सामान्य दिशानिर्देशों के साथ आ सकते हैं कि क्या कुछ स्क्रिप्ट या फ़ंक्शन / उपनाम बनाने के लिए।

  • क्या आपके खोल के अलावा अन्य कार्यक्रमों का उपयोग करने में सक्षम होना चाहिए? यदि हां, तो यह एक स्क्रिप्ट होना चाहिए।

  • क्या आप केवल यह चाहते हैं कि यह एक इंटरेक्टिव शेल से उपलब्ध हो? बाहरी आदेशों / लिपियों को प्रभावित किए बिना अंतःक्रियात्मक रूप से चलाने पर कई कमांडों के डिफ़ॉल्ट व्यवहार को बदलना चाहते हैं। इस मामले के लिए, एक उपनाम / समारोह खोल के "इंटरैक्टिव मोड-ओनली" आर सी फ़ाइल में सेट (के लिए उपयोग bashयह है .bashrc)।

  • क्या शेल के वातावरण को बदलने की आवश्यकता है? एक फ़ंक्शन / उपनाम या एक स्रोत वाली स्क्रिप्ट दोनों संभव विकल्प हैं।

  • क्या यह ऐसा कुछ है जिसका आप अक्सर उपयोग करते हैं? इसे स्मृति में रखने के लिए संभवतः अधिक कुशल है, इसलिए यदि संभव हो तो इसे फ़ंक्शन / उपनाम बनाएं।

  • इसके विपरीत, क्या यह कुछ ऐसा है जो आप केवल शायद ही कभी उपयोग करते हैं? उस स्थिति में, यह समझ में नहीं आता है कि जब आपको इसकी आवश्यकता नहीं है, तो यह हॉग मेमोरी है, इसलिए इसे स्क्रिप्ट बनाएं।


They जबकि फ़ंक्शंस और उपनामों में कुछ महत्वपूर्ण अंतर हैं, उन्हें एक साथ समूहीकृत किया जाता है क्योंकि फ़ंक्शंस एलियंस सब कुछ कर सकते हैं। उपनाम में स्थानीय चर नहीं हो सकते हैं और न ही वे तर्क प्रक्रिया कर सकते हैं, और वे एक पंक्ति से अधिक समय तक किसी भी चीज के लिए असुविधाजनक हैं।

System यूनिक्स प्रणाली में प्रत्येक चल रही प्रक्रिया में एक वातावरण होता है जिसमें variable=valueजोड़े का एक समूह होता है जिसमें अक्सर वैश्विक कॉन्फ़िगरेशन सेटिंग्स होती हैं, जैसे LANGकि डिफ़ॉल्ट लोकेल और PATHनिष्पादन योग्य खोज पथ को निर्दिष्ट करने के लिए।


26
IMHO यह सबसे अच्छा जवाब है।
ल्यूक एम

4
प्रश्न / उत्तर प्रारूप एक महान विचार है। मैं चोरी कर सकता हूँ। ;-)
मिकेल

4
वर्थ नोटिंग: यदि दो (या अधिक) स्क्रिप्ट को कुछ कोड साझा करने की आवश्यकता है, तो संभवतः उस कोड को एक फ़ंक्शन में डालना सबसे अच्छा है जो स्वयं एक तीसरी फ़ाइल में स्थित है जो उन दोनों स्क्रिप्ट को आयात / स्रोत करता है।
kbolino

3
प्रश्नों की उस सूची में जोड़ने के लिए एक और आइटम: क्या आपको कभी मक्खी पर कमांड में कार्यक्षमता बदलने की आवश्यकता है? एक स्क्रिप्ट में परिवर्तन सभी सत्रों में परिलक्षित होगा, जबकि कार्यों और उपनामों को प्रति सत्र के आधार पर पुनः लोड या पुनर्परिभाषित किया जाना चाहिए।
स्ट्रेटस

3
अच्छा उत्तर। एक और महत्वपूर्ण बात (मेरे लिए): अन्य बर्तनों के लिए "शॉर्टकट" बनाते समय, एक उपनाम का उपयोग करना बेहतर होता है क्योंकि मौजूदा स्वतः पूर्णता केवल उपनाम के साथ काम करेगी, लेकिन स्क्रिप्ट या फ़ंक्शन के साथ नहीं (इसलिए उपनामों के लिए +1)। उदा। alias g='gradle'अपने gउपनाम का उपयोग करते समय मुझे एक ढाल स्वत: पूर्णता प्राप्त होती है , लेकिन स्क्रिप्ट के साथ gradle $*या किसी फ़ंक्शन का उपयोग करते समय इसे आउट-ऑफ-द-बॉक्स नहीं मिलेगाgradle $@
Yoav Aharoni

37

मुझे लगता है कि यह प्रत्येक व्यक्ति के स्वाद पर निर्भर है। मेरे लिए तर्क कुछ इस तरह है:

  • पहले मैं एक उपनाम बनाने की कोशिश करता हूं, क्योंकि यह सबसे सरल है।
  • अगर बात एक लाइन में फिट होने के लिए बहुत जटिल है, तो मैं इसे एक फंक्शन बनाने की कोशिश करता हूं।
  • जब एक दर्जन लाइनों से आगे बढ़ना शुरू होता है, तो मैं इसे एक स्क्रिप्ट में डाल देता हूं।

वास्तव में ऐसा कुछ करने से प्रतिबंधित करने के लिए कुछ भी नहीं है जो काम करता है


6
मैं अक्सर फ़ंक्शन विकल्प को छोड़ देता हूं, और तुरंत एक स्क्रिप्ट बनाता हूं। लेकिन मैं मानता हूं कि यह आंशिक रूप से स्वाद की बात है
बर्नहार्ड

2
यदि आप इसे कई लिपियों में चाहते हैं तो एक फ़ंक्शन समझ में आने लगता है।
निल्स

7
... या यदि आपको वर्तमान शेल को बदलने के लिए साइड-इफेक्ट्स की आवश्यकता है ।
ग्लेन जैकमैन

समझ में आता है, यार!
खोजकर्ता

15

कम से कम आंशिक रूप से यह व्यक्तिगत स्वाद की बात है। दूसरी ओर कुछ स्पष्ट कार्यात्मक भेद हैं:

  • उपनाम: केवल सरल पाठ प्रतिस्थापन के लिए उपयुक्त, कोई तर्क / पैरामीटर नहीं
  • कार्य: लिखने / उपयोग करने में आसान, फुल शेल स्क्रिप्टिंग क्षमता, केवल बैश के अंदर उपलब्ध
  • स्क्रिप्ट: कमोबेश सभी प्रकार के कार्य, लेकिन उपलब्ध (कॉल करने योग्य) बैश के बाहर भी

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

पुनश्च: जैसा कि alias command="bash bashscriptname"मैंने वास्तव में ऐसा करने का कोई कारण नहीं देखा है। यहां तक ​​कि अगर bashscriptname$ पेट में नहीं है, तो एक साधारण alias c=/path/to/scriptपर्याप्त होगा।


1
में alias command="bash bashscriptname"स्क्रिप्ट जरूरी निष्पादन योग्य होने के लिए नहीं है, में alias c=/path/to/scriptइसे करने के लिए है।
मार्टिन -। チ ン -

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

@tripleee का अर्थ अधिक था "आप exec()कार्य नहीं कर सकते " :-)
nohillside

11

यहाँ उपनाम और कार्यों के बारे में कुछ अतिरिक्त बिंदु दिए गए हैं:

  • समान नाम वाला उपनाम और फ़ंक्शन सह-अस्तित्व में हो सकता है
  • उपनाम नाम स्थान पहले देखा गया है (पहला उदाहरण देखें)
  • उपनाम या गैर-संवादात्मक वातावरण में सेट (संयुक्त राष्ट्र) नहीं हो सकता है (दूसरा उदाहरण देखें)

उदाहरण के लिए:

alias f='echo Alias'; f             # prints "Alias"
function f { echo 'Function'; }; f  # prints "Alias"
unalias f; f                        # prints "Function"

जैसा कि हम देख सकते हैं, उपनाम और कार्यों के लिए अलग-अलग नाम स्थान हैं; अधिक विवरण का उपयोग करके पाया जा सकता है declare -A -p BASH_ALIASESऔर declare -f f, जो उनकी परिभाषाओं को प्रिंट करता है (दोनों मेमोरी में संग्रहीत हैं)।

एलियासेस की सीमाएँ दिखाने वाला उदाहरण:

alias a='echo Alias'
a        # OK: prints "Alias"
eval a;  # OK: prints "Alias"
( alias a="Nested"; a );  # prints "Alias" (not "Nested")
( unalias a; a );         # prints "Alias"
bash -c "alias aa='Another Alias'; aa"  # ERROR: bash: aa: command not found

जैसा कि हम देख सकते हैं कि उपनाम कार्यों के विपरीत, घोंसला नहीं हैं। साथ ही, उनका उपयोग इंटरैक्टिव सत्रों तक सीमित है।

अंत में, ध्यान दें कि आप किसी फ़ंक्शन को तुरंत कॉल करके एक उपनाम में मनमानी गणना कर सकते हैं, जैसे:

alias a_complex_thing='f() { do_stuff_in_function; } f'

जो पहले से ही Git aliases के मामले में व्यापक उपयोग में है। एक फ़ंक्शन घोषित करने पर ऐसा करने का लाभ यह है कि आपके उपनाम को केवल स्रोत-आईएनजी (या उपयोग करके .) एक स्क्रिप्ट को अधिलेखित नहीं किया जा सकता है जो एक समान नाम वाले फ़ंक्शन को घोषित करने के लिए होता है।


10

जब एक स्क्रिप्ट लिखने के लिए ...

  • स्क्रिप्ट सॉफ़्टवेयर घटकों (उर्फ उपकरण, कमांड, प्रक्रिया, निष्पादन, कार्यक्रम) को अधिक जटिल घटकों में इकट्ठा करता है, जो स्वयं को अभी भी अधिक जटिल घटकों में इकट्ठा किया जा सकता है।
  • लिपियों को आमतौर पर निष्पादन योग्य बनाया जाता है ताकि उन्हें नाम से बुलाया जा सके। जब कॉल किया जाता है, तो स्क्रिप्ट को चलाने के लिए एक नया सबप्रोसेस दिया जाता है। किसी भी exportएड वैरिएबल्स और / या फ़ंक्शंस की कॉपियाँ स्क्रिप्ट के मान से पास की जाती हैं । उन चर में परिवर्तन मूल स्क्रिप्ट में वापस नहीं फैलता है।
  • लिपियों को भी लोड (खट्टा) किया जा सकता है जैसे कि वे कॉलिंग स्क्रिप्ट का हिस्सा थे। यह कुछ अन्य भाषाओं को "आयात" या "शामिल" कहता है। जब यह किया जाता है, तो वे मौजूदा प्रक्रिया के भीतर निष्पादित होते हैं। कोई उपप्रकार नहीं है।

जब एक समारोह लिखने के लिए ...

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

जब एक उपनाम लिखने के लिए ...

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

# A bash in-script 'alias'
function oldFunction () { newFunction "$@"; }

9

एक और चीज जो मुझे विश्वास नहीं है कि लाई गई है: एक प्रक्रिया आह्वान प्रक्रिया के संदर्भ में निष्पादित होती है, जबकि एक स्क्रिप्ट एक नए शेल की तलाश करती है।

यह प्रदर्शन के लिए महत्वपूर्ण हो सकता है - एक फ़ंक्शन तेज़ है, क्योंकि यह नहीं है fork()और exec()। सामान्य परिस्थितियों में, अंतर तुच्छ है, लेकिन अगर आप एक ऐसी प्रणाली को डिबग कर रहे हैं जो मेमोरी से बाहर है और पेज-थ्रैशिंग है, तो यह एक बड़ा अंतर ला सकता है।

इसके अलावा, यदि आप अपने वर्तमान शेल वातावरण को संशोधित करना चाहते हैं, तो आपको एक फ़ंक्शन का उपयोग करना चाहिए। उदाहरण के लिए, एक फ़ंक्शन $PATHवर्तमान शेल के लिए कमांड लुकअप को बदल सकता है , लेकिन एक स्क्रिप्ट नहीं कर सकता है, क्योंकि यह एक फोर्क / कॉपी पर निष्पादित होता है $PATH


बच्चों के लिए कार्यों का यह प्रसार कैसे काम करता है?
हैप्पीफेस

1
@HappyFace बैश में आप export -fएक फंक्शन कर सकते हैं, हालांकि इसके सटीक आंतरिक कामकाज कुछ अस्पष्ट हैं। मेरा मानना ​​है कि यह पारंपरिक बॉर्न शेल के लिए पोर्टेबल नहीं है।
16

7

स्क्रिप्ट और उपनाम और स्क्रिप्ट और फ़ंक्शन परस्पर अनन्य नहीं हैं। आप स्क्रिप्ट में उपनाम और फ़ंक्शंस स्टोर कर सकते हैं।

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

चूंकि उपनामों को परिचालित नहीं किया जाता है , वे बहुत सीमित हैं; आमतौर पर कुछ डिफ़ॉल्ट मापदंडों को परिभाषित करने के लिए।

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


5

यदि यह बहुत तेज़ होना चाहिए, तो इसे एक उपनाम या एक फ़ंक्शन बनाएं।

यदि यह आपके पसंदीदा शेल के बाहर प्रयोग करने योग्य होना चाहिए, तो इसे एक स्क्रिप्ट बनाएं। 1

यदि यह तर्क लेता है, तो इसे एक फ़ंक्शन या एक स्क्रिप्ट बनाएं।

यदि इसे विशेष वर्णों की आवश्यकता है, तो इसे एक उपनाम या एक स्क्रिप्ट बनाएं। 2

यदि उसे सूडो के साथ काम करने की आवश्यकता है, तो इसे एक उपनाम या एक स्क्रिप्ट बनाएं। 3

यदि आप इसे लॉग आउट और बिना आसानी से बदलना चाहते हैं, तो एक स्क्रिप्ट आसान है। 4

फुटनोट

1 या इसे एक उर्फ ​​बनाएं, इसे अंदर रखें ~/.envऔर सेट करें export ENV="$HOME/.env", लेकिन इसे जटिल रूप से काम करना जटिल है।

2 फ़ंक्शन नामों को पहचानकर्ता होना चाहिए, इसलिए उन्हें एक पत्र के साथ शुरू करना होगा, और केवल पत्र, अंक और अंडरस्कोर हो सकते हैं। उदाहरण के लिए, मेरे पास एक उपनाम है alias +='pushd +1'। यह एक फ़ंक्शन नहीं हो सकता।

3 और उपनाम जोड़ें alias sudo='sudo '। डिट्टो किसी अन्य आदेश जैसे strace, gdbआदि है कि इसके पहले तर्क के रूप में एक आदेश लेता है।

4 इन्हें भी देखें: fpath बेशक आप भी कर सकते हैं source ~/.bashrcया इसी तरह, लेकिन यह अक्सर अन्य दुष्प्रभाव हैं।


1
मुझे नहीं पता था कि आप +बैश में उपनाम रख सकते हैं । दिलचस्प बात यह है कि परीक्षण के बाद मुझे पता चला कि बाश में आप +एक उपनाम बना सकते हैं लेकिन एक फ़ंक्शन नहीं, जैसा कि आप कहते हैं, लेकिन zsh रिवर्स है - +एक फ़ंक्शन हो सकता है लेकिन अन्य नहीं।
केविन

में zshआप लिखने के लिए है alias -- +='some command here'
मिकेल

किसी तरह, मुझे नहीं लगता कि अलियासिंग +पोर्टेबल है।
उपनामों

3
sudoउपयोग को कवर करने के लिए अपवोट । फुटनोट 4 के बारे में, मैं अपने उपनामों को ~/.bash_aliasesऔर कार्य परिभाषाओं में संग्रहीत करता हूं ~/.bash_functionsताकि मैं sourceउन्हें आसानी से (बिना किसी साइड इफेक्ट के खतरे के) पुन: प्राप्त कर सकूं।
एंथोनी गोगेगन

3

बस कुछ नोट्स जोड़ने के लिए:

  • उदाहरण के लिए केवल अलग-अलग स्क्रिप्ट का उपयोग सूडो के साथ किया जा सकता है (जैसे अगर आपको किसी सिस्टम फ़ाइल को संपादित करने की आवश्यकता है):
sudo v /etc/rc.conf  #where v runs vim in a new terminal window;
  • केवल उपनाम या फ़ंक्शन समान नाम के तहत सिस्टम कमांड को प्रतिस्थापित कर सकते हैं (यह मानते हुए कि आप अपनी स्क्रिप्ट को PATH के अंत में जोड़ते हैं, जो मुझे लगता है कि सिस्टम कमांड के समान नाम के साथ स्क्रिप्ट के आकस्मिक या पुरुषवादी निर्माण के मामले में सुरक्षा के लिए सलाह दी जाती है), उदाहरण के लिए:
alias ls='ls --color=auto'  #enable colored output;
  • उपनाम और कार्य निष्पादन के लिए कम मेमोरी और समय लेते हैं, लेकिन लोड करने में समय लेते हैं (क्योंकि शेल को आपको शीघ्र दिखाने से पहले उन सभी की व्याख्या करनी होगी)। उदाहरण के लिए, यदि आप नियमित रूप से नई शेल प्रक्रिया चलाते हैं, तो इसे ध्यान में रखें:
# pressing key to open new terminal
# waiting for a few seconds before shell prompt finally appears.

इसके अलावा, आप सबसे सरल रूप का उपयोग कर सकते हैं, अर्थात पहले उपनाम, फिर कार्य, फिर स्क्रिप्ट पर विचार करें।


5
उपनाम के साथ भी इस्तेमाल किया जा सकता है sudo। लेकिन पहले आपको जरूरत है alias sudo='sudo '
मिकेल

हालांकि यह सच है कि किसी स्क्रिप्ट को निष्पादित करने से फोर्क + निष्पादन की अवधि के लिए अधिक मेमोरी का उपभोग होगा, वर्तमान शेल इंस्टेंस की मेमोरी में बहुत सारे कोड लोड होने से यह अधिक मेमोरी को आगे ले जाने में सक्षम बनाता है, अक्सर कोड को स्टोर करने के लिए जो केवल काफी कम इस्तेमाल किया जाता है।
ट्रिपलए

2

अंगूठे का मेरा नियम है:

  • उपनाम - एक आदेश, कोई पैरामीटर नहीं
  • फ़ंक्शंस - एक कमांड कुछ मापदंडों
  • स्क्रिप्ट - कई कमांड, कोई पैरामीटर नहीं

1

एक बहु उपयोगकर्ता (या मल्टी सिस्मिन) वातावरण में, मैं सब कुछ के लिए स्क्रिप्ट का उपयोग करता हूं, भले ही यह समाप्त हो जाए एक संक्षिप्त 'कुछ निष्पादित करें ....' आवरण।

निश्चित रूप से, यह तकनीकी रूप से धीमा है / एक अन्य या फ़ंक्शन की तुलना में कम कुशल है, लेकिन यह लगभग कभी मायने नहीं रखता है - और यह पथ में प्रदान किया गया है, एक स्क्रिप्ट हमेशा काम करती है।

आपकी सुविधा को क्रोन से कहा जा सकता है, सूडो या एनवी जैसे कम या संशोधित वातावरण के साथ कुछ से, या उपयोगकर्ता केवल आपके लिए एक अलग शेल का उपयोग कर सकता है - सभी या जो एक उपनाम या फ़ंक्शन को तोड़ने की संभावना है।

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

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

टी


0

एक स्थिति के लिए एक उदाहरण जहां आप सबसे अधिक पसंद करते हैं एक उपनाम का उपयोग करना चाहते हैं।

मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन मैं एक ऐसी स्थिति को इंगित करना चाहूंगा जहां मुझे लगभग एक स्क्रिप्ट के साथ उपनाम का उपयोग करना पड़ा था और मैंने एक फ़ंक्शन का उपयोग नहीं करने का विकल्प चुना।

मेरे पास एक स्क्रिप्ट है ~/.bin/जिसे setupनिम्नलिखित कहा जाता है: 1

  1. मुझे एक निश्चित निर्देशिका में लाता है।
  2. कुछ चर को परिभाषित करता है।
  3. निर्देशिका की स्थिति के बारे में संदेश प्रिंट करता है। 2

मुद्दा यह है कि अगर मैं बस चलाऊंगा तो मेरे setup <project-name>पास उन चरों को परिभाषित नहीं किया जाएगा और मुझे निर्देशिका बिल्कुल नहीं मिलेगी। समाधान मैं सबसे अच्छा हो पाया करने के लिए इस स्क्रिप्ट जोड़ने के लिए गया था PATHऔर जोड़ने alias setup=". ~/.bin/setup"के लिए ~/.bashrcया जो कुछ भी।

टिप्पणियाँ:

  1. मैंने इस कार्य के लिए एक स्क्रिप्ट का उपयोग किया है और एक फ़ंक्शन का नहीं, क्योंकि यह विशेष रूप से लंबा नहीं है, क्योंकि मैं इसे संपादित कर सकता हूं और मुझे संपादित करने के बाद फ़ाइल को स्रोत नहीं करना है अगर मैं इसे उपयोग करना चाहता हूं।
  2. इसी तरह का एक मामला मेरे सामने आया जब मैंने अपने सभी डॉटफाइल्स को फिर से लोड करने के लिए एक स्क्रिप्ट बनाई। 3
  1. स्क्रिप्ट में उपलब्ध है मेरी dotfiles भंडार के तहत .bin/
  2. स्क्रिप्ट के बारे में : मैं इस स्क्रिप्ट को एक तर्क देता हूं, जो उस प्रोजेक्ट का एक नाम है जिसे मैंने एडवांस में परिभाषित किया है। बाद में स्क्रिप्ट मुझे एक निश्चित csvफ़ाइल के अनुसार सही निर्देशिका में लाने के लिए जानता है । इसे परिभाषित करने वाले चर उस निर्देशिका में मेकफाइल से लिए गए हैं। स्क्रिप्ट बाद में चलती है ls -lऔर git statusमुझे दिखाने के लिए कि वहां क्या चल रहा है।
  3. वह स्क्रिप्ट मेरे डॉटफाइल्स रिपॉजिटरी में भी उपलब्ध है .bin/

1
हम्म, लगता है कि सिर्फ एक फ़ंक्शन होना चाहिए, न कि एक उपनाम-स्क्रिप्ट संयोजन। (BTW, वातावरण "वातावरण" वर्तनी है "नहीं"।)
वाइल्डकार्ड

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

0

स्क्रिप्ट कब लिखनी है

जब आप शेल के अलावा किसी टूल से कमांड चलाना चाहते हैं।

इसमें vim (मेरे लिए) शामिल है: स्क्रिप्ट के रूप में लिखित फ़िल्टर और अन्य प्रोग्राम होने पर, मैं :%!my-filterअपने संपादक के साथ प्रोग्राम के माध्यम से फ़ाइल को फ़िल्टर करने के लिए कुछ कर सकता हूं।

यदि my-filterएक समारोह या अन्य नाम थे, तो यह संभव नहीं होगा।

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