वर्णमाला के साथ लूप के लिए


12

यह पूरी तरह से OSX पर काम करता है

#!/bin/bash
chars=( {a..z} )
n=3
for ((i=0; i<n; i++))
do
  echo "${chars[i]}"
done

लेकिन जब मैं इसे उबंटू पर चलाता हूं, तो मुझे निम्नलिखित त्रुटि मिलती है।

ForLoopAlphabetTest.sh: 2: ForLoopAlphabetTest.sh: Syntax error: "(" unexpected

मैं इस मुद्दे को हल करने के लिए प्रतीत नहीं कर सकता। कोई सुझाव?


2
यह उबंटू पर काम करता है।
पायलट 6

मैं इसे स्क्रिप्ट के रूप में 16.04 bash 4.3 पर काम नहीं कर सकता। लेकिन यह काम करता है अगर मैं इसे टर्मिनल में कॉपी करता हूं।
डेंसकी

जवाबों:


25

संभवतः, आप स्क्रिप्ट को इस प्रकार चला रहे हैं:

sh ForLoopAlphabetTest.sh

उबंटू में, इसके shलिए सहानुभूति है dash; जैसा dashकि सरणियों की कोई अवधारणा नहीं है, आपको इसके लिए वाक्यविन्यास त्रुटि मिल रही है (

स्क्रिप्ट पूरी तरह से काम करती है bash, इसलिए यह ठीक होगा यदि आप इसे bashतर्क के रूप में चला रहे हैं :

bash ForLoopAlphabetTest.sh

अब, आपके पास bashस्क्रिप्ट पर शेबंग है, इसलिए आप स्क्रिप्ट को निष्पादन योग्य बना सकते हैं ( chmod u+x ForLoopAlphabetTest.sh), और इसे इस रूप में चलाएं:

/path/to/ForLoopAlphabetTest.sh

या स्क्रिप्ट की निर्देशिका से:

./ForLoopAlphabetTest.sh

यह भी ध्यान दें कि, आपकी स्क्रिप्ट में ब्रेस विस्तार {a..z}और सी-स्टाइल forनिर्माण शामिल हैं: for (( ... ))जो भी समर्थित नहीं हैं dash; इसलिए यदि आपका लक्ष्य पोर्टेबिलिटी है, तो आपको POSIX shसिंटैक्स को ही देखना चाहिए ।


धन्यवाद। क्या डैश की सरणी की अवधारणा की कमी को दरकिनार करने का एक तरीका है?
डेन्स्की

3
@ डेंसकी यदि आप पोर्टेबल स्क्रिप्ट लिखना चाहते हैं, जो /bin/shकिसी भी यूनिक्स जैसे ऑपरेटिंग सिस्टम पर चलाया जा सकता है, तो आप सरणियों का उपयोग करने में सक्षम नहीं होंगे। बैश (और कुछ अन्य गोले) ने उन्हें जोड़ा है क्योंकि वे बहुत सुविधाजनक हैं और हमेशा आसानी से अधिक पोर्टेबल कोड के साथ प्रतिस्थापित नहीं किए जा सकते हैं। हालांकि, विशेष रूप से आपकी स्क्रिप्ट के लिए, आप इसे बिना किसी परेशानी और बिना किसी विशिष्ट-विशिष्ट सुविधाओं का उपयोग किए कर सकते हैं। क्या आप ऐसा करने में रुचि रखते हैं?
एलियाह कगन

यदि आपके पास कुछ सुझाव दिए गए हैं जो मददगार होंगे। धन्यवाद।
डेन्सकी

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

@heemayl रिकॉर्ड के लिए, मैं यह जोड़ना चाहता था कि आप अपनी धारणा में सही थे कि मैं स्क्रिप्ट के साथ चल रहा थाsh
denski

10

आपकी स्क्रिप्ट बैश शेल की तीन विशेषताओं का उपयोग करती है जो सभी बॉर्न-शैली के गोले द्वारा प्रदान नहीं की जाती हैं। जैसा कि हेमायल कहते हैं , आप केवल उस स्क्रिप्ट को bashइसके बजाय चला सकते हैं sh। शीर्ष पर आपकी हैशबैंग लाइन ( #!/bin/bash) निर्दिष्ट है, bashलेकिन केवल तभी प्रभावी है जब आप स्क्रिप्ट निष्पादित करते हैं, जैसा कि हेमायल ने समझाया था । यदि आप स्क्रिप्ट का नाम पास करते हैं sh, shतो स्वचालित रूप से कॉल नहीं करेगा bash, लेकिन बस स्क्रिप्ट चलाएगा। ऐसा इसलिए है क्योंकि एक बार जब आपकी स्क्रिप्ट वास्तव में चल रही होती है, तो हैशबैंग लाइन का कोई प्रभाव नहीं पड़ता है

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

  • एक सरणी । यह पहली बार आया था, इसलिए जब आप अपने स्क्रिप्ट को डैश शेल से चलाने का प्रयास करते हैं तो यह त्रुटि उत्पन्न होती है । कोष्ठबद्ध अभिव्यक्ति ( {a..z} ), जिसे आप असाइन करते हैं chars, एक सरणी बनाता है, और ${chars[i]}, जो आपके लूप में दिखाई देता है, उसमें अनुक्रमित होता है।
  • ब्रेस विस्तार। बैश में, और भी कई अन्य गोले में, {a..z}का विस्तार किया जाता है a b c d e f g h i j k l m n o p q r s t u v w x y z। हालाँकि, यह बॉर्न-शैली के गोले की एक सार्वभौमिक (या मानकीकृत) विशेषता नहीं है, और डैश इसका समर्थन नहीं करता है।
  • सी-शैली वैकल्पिक for-लूप वाक्य रचना । हालांकि के आधार पर गणित विस्तार है, जो है बैश के लिए विशिष्ट ही नहीं (हालांकि कुछ बहुत पुरानी, गैर POSIX अनुरूप गोले यह नहीं है, या तो), सी शैली forपाश है एक बैश-वाद और व्यापक रूप से करने के लिए पोर्टेबल नहीं है अन्य गोले।

बैश व्यापक रूप से उपलब्ध है, खासकर GNU / Linux सिस्टम पर जैसे Ubuntu, और (जैसा कि आपने देखा है) macOS और कई अन्य प्रणालियों पर भी उपलब्ध है। यह देखते हुए कि आप बैश-विशिष्ट सुविधाओं का कितना उपयोग कर रहे हैं, आप शायद उनका उपयोग करना चाहते हैं, और बस सुनिश्चित करें कि आप अपनी स्क्रिप्ट चलाने के दौरान बैश का उपयोग कर रहे हैं (या कुछ अन्य शेल जो आपके द्वारा उपयोग की जा रही सुविधाओं का समर्थन करते हैं)।

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


सबसे पहले, यहां एक स्क्रिप्ट है जो सभी निचले-केस लैटिन अक्षरों को प्रिंट करती है:

#!/bin/sh

for i in $(seq 97 122); do
    printf "\\$(printf %o $i)\n"
done

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

#!/bin/sh

i=97
while [ $i -le 122 ]; do
    printf "\\$(printf %o $i)\n"
    i=$((i + 1))
done

यह आदेश में लूपिंग जारी रखने के लिए आदेश केwhile साथ एक लूप का उपयोग करता है ।[$i


पूरे वर्णमाला को प्रिंट करने के बजाय, आपकी स्क्रिप्ट एक चर को परिभाषित करती है nऔर पहले $nनिचले-मामले के अक्षरों को प्रिंट करती है । यहां आपकी स्क्रिप्ट का एक संस्करण है जो डैश-आधारित सुविधाओं और डैश पर काम करने पर निर्भर करता है, लेकिन इसके लिए आवश्यक है seq:

#!/bin/sh

n=3 start=97
for i in $(seq $start $((start + n - 1))); do
    printf "\\$(printf %o $i)\n"
done

nपरिवर्तनों के मूल्य को समायोजित करना कि आपकी स्क्रिप्ट में कितने अक्षर मुद्रित हैं।

यहां एक ऐसा संस्करण है जिसकी आवश्यकता नहीं है seq:

#!/bin/sh

n=3 i=97 stop=$((i + n))
while [ $i -lt $stop ]; do
    printf "\\$(printf %o $i)\n"
    i=$((i + 1))
done

वहाँ, अंतिम पत्र के चरित्र कोड से $stopएक अधिक है जिसे मुद्रित किया जाना चाहिए, इसलिए मैं कमांड के साथ (कम या बराबर) के -ltबजाय -le(कम से कम ) का उपयोग करता हूं [। (इसे बनाने stop=$((i + n - 1))और उपयोग करने के लिए भी काम किया होगा [ $i -le $stop ])।


1
यह शिक्षा के लिए आप की तुलना में एक अभूतपूर्व विस्तृत जवाब है। मैं बहुत शुरुआती हूं, इसलिए स्क्रिप्ट लिखने का मेरा तरीका काम करने वाले तत्वों को इंटरनेट पर एक साथ काम करता है जब तक कि यह काम नहीं करता है। मुझे इसमें कोई संदेह नहीं है कि 1) बेहतर और 2) सरल तरीके हैं जो मैं स्क्रिप्ट के साथ बना रहा हूं और उपरोक्त उस से मदद करने के लिए एक लंबा रास्ता तय करता है।
डेन्स्की

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