यह स्क्रिप्ट टर्मिनल में काम क्यों करती है लेकिन किसी फाइल से नहीं?


19

मेरे पास यह शेल स्क्रिप्ट एक फ़ाइल में सहेजी गई है: यह कुछ बुनियादी स्ट्रिंग प्रतिस्थापन करती है।

#!/bin/sh
html_file=$1
echo "html_file = $html_file"
substr=.pdf
pdf_file="${html_file/.html/.pdf}"
echo "pdf_file = $pdf_file"

अगर मैं इसे कमांड लाइन में पेस्ट करता हूं, तो यह ठीक काम करता है:

$ html_file="/home/max/for_pauld/test_no_base64.html"
  echo "html_file = $html_file"
  substr=.pdf
  pdf_file="${html_file/.html/.pdf}"
  echo "pdf_file = $pdf_file"

देता है

html_file = /home/max/for_pauld/test_no_base64.html
pdf_file = /home/max/for_pauld/test_no_base64.pdf

कि ऊपर से इको से आउटपुट है - यह इरादा के अनुसार काम कर रहा है।

लेकिन, जब मैं स्क्रिप्ट को कॉल करता हूं, के साथ

$ saucer "/home/max/for_pauld/test_no_base64.html"

मुझे यह आउटपुट मिलता है:

html_file = /home/max/for_pauld/test_no_base64.html
/home/max/bin/saucer: 5: /home/max/bin/saucer: Bad substitution

क्या मेरी स्क्रिप्ट बैश या कुछ और के एक अलग संस्करण का उपयोग कर रही है? क्या मुझे अपनी शेबंग लाइन बदलने की जरूरत है?


6
वह पैरामीटर विस्तार एक बशीवाद (अच्छी तरह से, गैर-पॉसिक्स) है: अपना शेल्हांग बदलें।
जसोनव्रीयन

धन्यवाद! वह काम किया। मुझे लगता है कि मैं shऔर के बीच के अंतर पर थोड़ा धुंधला हूँ bash। मैं उस पर पढ़ूंगा। यदि आप अपनी टिप्पणी को एक उत्तर देने के लिए परेशान कर सकते हैं, तो मैं इसे सही चिह्नित करूंगा।
मैक्स विलियम्स

अपने विस्तृत उत्तर के लिए द ड्यूक को टिक दिया, लेकिन फिर भी धन्यवाद।
मैक्स विलियम्स

2
@MaxWilliams: संक्षेप में, मूल बोर्न शेल है। सभी संगत लिपियों को श के लिए लिखा जाना चाहिए। लेकिन कई बाद के गोले (उदा: बाश, बॉर्न अगेन शेल) "लगभग संगत" हैं और बहुत अधिक अतिरिक्त सुंदरता जोड़ते हैं। जैसे कि आपके द्वारा उपयोग किया जाने वाला प्रतिस्थापन। आजकल, आप केवल पॉज़िक्स सुविधाओं का उपयोग करके काफी सुरक्षित हैं, लेकिन ध्यान रखें कि पोर्टेबिलिटी एक संकरा सेट (यानी केवल sh) पर भी निर्भर करती है। तो सामान्य तौर पर, उपयोग करें: #!/usr/bin/env bashअपने शेबंग के रूप में, और अपनी इच्छा के अनुसार सकारात्मक परिभाषित प्रतिस्थापन का उपयोग करें, लेकिन पोर्टेबिलिटी केविट के साथ। और पढ़ें: unix.stackexchange.com/a/48787/27616
ओलिवियर

जवाबों:


37

श क्या है?

sh(या शेल कमांड लैंग्वेज) POSIX मानक द्वारा वर्णित एक प्रोग्रामिंग भाषा है । यह कई कार्यान्वयन है ( ksh88, dash, ...)। bashका कार्यान्वयन भी माना जा सकता है sh(नीचे देखें)।

क्योंकि shएक विनिर्देश है, एक कार्यान्वयन नहीं है, /bin/shअधिकांश पॉसिक्स सिस्टम पर वास्तविक कार्यान्वयन के लिए एक सिमलिंक (या एक कठिन लिंक) है।

बैश क्या है?

bashएक shअसंगत कार्यान्वयन के रूप में शुरू किया गया था (हालांकि यह कुछ वर्षों से POSIX मानक से पहले का है), लेकिन समय बीतने के साथ-साथ इसने कई एक्सटेंशन हासिल कर लिए हैं। इनमें से कई एक्सटेंशन वैध POSIX शेल स्क्रिप्ट के व्यवहार को बदल सकते हैं, इसलिए अपने आप bashमें एक मान्य POSIX शेल नहीं है। बल्कि, यह POSIX खोल भाषा की एक बोली है।

bashएक --posixस्विच का समर्थन करता है , जो इसे अधिक POSIX- अनुरूप बनाता है। यह भी POSIX की नकल करने की कोशिश करता है अगर के रूप में आमंत्रित किया sh

श = बाश?

लंबे समय तक, अधिकांश GNU / Linux सिस्टम /bin/shको इंगित करने के लिए उपयोग किया जाता है /bin/bash। नतीजतन, दोनों के बीच के अंतर को अनदेखा करना लगभग सुरक्षित हो गया था। लेकिन वह हाल ही में बदलना शुरू हुआ।

सिस्टम के कुछ लोकप्रिय उदाहरण जहां /bin/shइंगित नहीं करते हैं /bin/bash(और जिनमें से कुछ /bin/bashभी मौजूद नहीं हो सकते हैं) हैं:

  1. आधुनिक डेबियन और उबंटू सिस्टम, जो डिफ़ॉल्ट रूप shसे सहानुभूति रखते हैं dash;
  2. बिजीबॉक्स , जो आमतौर पर लिनक्स सिस्टम बूट समय के दौरान चलाया जाता है initramfs। यह ashशेल कार्यान्वयन का उपयोग करता है ।
  3. बीएसडी और सामान्य रूप से कोई भी गैर-लिनक्स सिस्टम। OpenBSD pdksh, कॉर्न शेल के वंशज का उपयोग करता है । FreeBSD shमूल UNIX बॉर्न शेल का एक वंशज है। सोलारिस का अपना है shजो लंबे समय तक पोसिक्स-अनुरूप नहीं था; हिरलूम परियोजना से एक नि: शुल्क कार्यान्वयन उपलब्ध है ।

आप कैसे पता लगा सकते हैं कि /bin/shआपके सिस्टम पर क्या अंक हैं?

जटिलता यह है कि /bin/shएक प्रतीकात्मक लिंक या एक कड़ी हो सकती है। यदि यह एक प्रतीकात्मक लिंक है, तो इसे हल करने का एक पोर्टेबल तरीका है:

% file -h /bin/sh
/bin/sh: symbolic link to bash

यदि यह एक कड़ी है, तो प्रयास करें

% find -L /bin -samefile /bin/sh
/bin/sh
/bin/bash

वास्तव में, -Lध्वज में सहानुभूति और हार्डलिंक दोनों शामिल हैं, लेकिन इस पद्धति का नुकसान यह है कि यह पोर्टेबल नहीं है - POSIX को विकल्प का समर्थन करने की आवश्यकता नहीं है , हालांकि GNU ढूंढते हैं और FreeBSD दोनों इसका समर्थन करते हैं।find-samefile

शेबंग लाइन

अंत में, यह आप पर तय करना है कि «शेबंग» लाइन लिखकर किसका उपयोग करना है।

उदाहरण के लिए

#!/bin/sh

का उपयोग करेगा sh(और जो कुछ भी इंगित करने के लिए होता है),

#!/bin/bash

का उपयोग करेगा /bin/bashअगर यह उपलब्ध है (और एक त्रुटि संदेश के साथ विफल अगर यह नहीं है)। बेशक, आप एक और कार्यान्वयन भी निर्दिष्ट कर सकते हैं, उदाहरण के लिए

#!/bin/dash

कौन सा उपयोग करना है

अपनी स्वयं की स्क्रिप्ट के लिए, मैं shनिम्नलिखित कारणों से पसंद करता हूं :

  • यह मानकीकृत है
  • यह बहुत सरल और सीखने में आसान है
  • यह POSIX प्रणालियों में पोर्टेबल है - भले ही वे न हों bash, उनके पास होना आवश्यक हैsh

bashसाथ ही उपयोग करने के फायदे हैं । इसकी विशेषताएं प्रोग्रामिंग को अन्य आधुनिक प्रोग्रामिंग भाषाओं में प्रोग्रामिंग के समान सुविधाजनक बनाती हैं। इनमें स्कॉप्ड लोकल वैरिएबल और एरेज़ जैसी चीजें शामिल हैं। सादा shएक बहुत न्यूनतर प्रोग्रामिंग भाषा है।


विस्तृत उत्तर के लिए धन्यवाद: मैं लिनक्स मिंट का उपयोग करता हूं जो डेबियन-आधारित है और /bin/shवास्तव में एक सिम्लिंक है /bin/dash
मैक्स विलियम्स

यदि आप पोसिक्स श का पालन करना चाहते हैं, तो शेबंग को पूरी तरह से छोड़ दें: यदि शेल कमांडों की फाइल की पहली पंक्ति "#!" अक्षर से शुरू होती है, तो परिणाम अनिर्दिष्ट pubs.opengroup.org/onlinebubs/009695399/ हैं उपयोगिताओं /…
डैनियल जर्स

4
@ डैनियलजोर यदि किसी भी यूनिक्स जैसी प्रणाली ने शेबंग के लिए सामान्य समर्थन को गिरा दिया तो यह बहुत सारी चीजों को तोड़ देगा यह व्यावहारिक रूप से अनुपयोगी होगा। तो यह एक वास्तविक मानक है, भले ही यह POSIX में निर्दिष्ट न हो। एकमात्र वास्तविक संगतता मुद्दा यह है कि दुभाषियों के लिए मार्ग भिन्न हो सकते हैं।
बरमार

23

@ Hunter.S.Thompson से उत्कृष्ट उत्तर को जोड़ना मैं यह बताना चाहूंगा कि स्क्रिप्ट का गैर-पोर्टेबल हिस्सा है

pdf_file="${html_file/.html/.pdf}"

${variable/search/replace}एक जीएनयू विस्तार है। लेकिन आप इसे आसानी से शुद्ध POSIX से बचा सकते हैं:

pdf_file="${html_file%.html}".pdf

हंटर के बाद, यह शेबंग को बदलने से बेहतर है #! /bin/bash


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

1
@MaxWilliams बेशक, कोई बात नहीं। यह मुख्य रूप से Q & A डेटाबेस के लिए दिया गया था।
फिलिप्पुस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.