शेल स्क्रिप्ट "लूप सिंटैक्स" के लिए


190

मैं काम करने के लिए निम्नलिखित है:

for i in {2..10}
do
    echo "output: $i"
done

यह लाइनों का एक गुच्छा पैदा करता है output: 2 , output: 3, इतने पर।

हालाँकि, निम्न को चलाने की कोशिश कर रहा है:

max=10
for i in {2..$max}
do
    echo "$i"
done

निम्नलिखित उत्पादन करता है:

output: {2..10}

मुझे इस बात का एहसास कैसे हो सकता है कि इसे सरणी के दूसरे छोर के रूप में $ अधिकतम का इलाज करना चाहिए, न कि एक स्ट्रिंग का हिस्सा?


2
आप किस सिस्टम और शेल का उपयोग कर रहे हैं? किस प्रकार की नासमझ प्रणाली में श या बैश है, लेकिन seq, एक कोरुटिल नहीं है?
whatsisname

11
FreeBSD नहीं करता है।
नीत्शे-जौ

echo "$iहोना चाहिए echo "$i"- से समस्या हल नहीं होगी, हालांकि।
डेव जार्विस

छोटे शैली निट: मैं आमतौर पर देखने doऔर thenके रूप में एक ही लाइन पर कीवर्ड forऔर if, क्रमशः। जैसे,for i in {2..10}; do
एक

जवाबों:


234

ब्रेस विस्तार, {x..y} अन्य विस्तार से पहले किया जाता है, इसलिए आप चर लंबाई अनुक्रम के लिए इसका उपयोग नहीं कर सकते हैं।

इसके बजाय, उपयोग करें seq 2 $max विधि का जैसा कि उपयोगकर्ता की भीड़ ने कहा है

तो, आपके उदाहरण के लिए यह होगा:

max=10
for i in `seq 2 $max`
do
    echo "$i"
done

बाहरी कमांड का उपयोग करने का कोई अच्छा कारण नहीं है जैसे कि seqलूप के लिए संख्याओं की गणना और वृद्धि करना, इसलिए यह अनुशंसा की जाती है कि आप उपयोग करने से बचें seq। यह आदेश पुराने बैश के साथ संगतता के लिए छोड़ दिया गया है। अंतर्निहित कमांड पर्याप्त तेज़ हैं। for (( EXP1; EXP2; EXP3 )) ...
मिलर

13
@miller for (( ... ))सिंटैक्स POSIX नहीं है और उदाहरण के लिए इसका मतलब है कि यह अल्पाइन लिनक्स जैसी चीजों पर बॉक्स से बाहर काम नहीं करेगा। seqकर देता है।
वेर्नेट

निश्चय ही अल्पाइन लिनक्स नहीं; #!/bin/shडेबियन / उबंटू में डैश है।
फ्रैंकलिन यू

72

के अंकगणितीय-अभिव्यक्ति संस्करण का प्रयास करें for:

max=10
for (( i=2; i <= $max; ++i ))
do
    echo "$i"
done

यह बैश के अधिकांश संस्करणों में उपलब्ध है, और बॉर्न शेल (श) संगत भी होना चाहिए।


1
@ फ़्लो: एचएम, मैंने इसे सिर्फ #! / Bin / sh के साथ सिस्टम (लिनक्स और BSD आधारित) के एक जोड़े पर आज़माया और यह ठीक काम किया। बैश के तहत और विशेष रूप से / बिन / श के तहत, अभी भी काम किया। शायद श के मामलों का संस्करण? क्या आप कुछ पुराने यूनिक्स पर हैं?
सिस्टम PAUSE

8
बहुत कम प्रणालियों में एक समर्पित होता है sh, इसके बजाय यह एक अन्य शेल के लिए एक लिंक बनाता है। आदर्श रूप में, इस तरह के शेल shको केवल POSIX मानक में उन सुविधाओं का समर्थन करने के लिए आमंत्रित किया जाता है , लेकिन डिफ़ॉल्ट रूप से कुछ अतिरिक्त सुविधाओं के माध्यम से। C- स्टाइल के लिए लूप एक POSIX फीचर नहीं है, लेकिन shवास्तविक शेल द्वारा मोड में हो सकता है ।
Chepner

27

लूप को मैन्युअल रूप से चरणबद्ध करें:

मैं = 0
अधिकतम = 10
जबकि [$ i-$ $ अधिकतम]
करना
    इको "आउटपुट: $ i"
    सच $ ((i ++))
किया हुआ

यदि आपको पूरी तरह से POSIX नहीं होना है, तो आप लूप के लिए अंकगणित का उपयोग कर सकते हैं :

अधिकतम = 10
((i = 0; मैं <अधिकतम; i ++)) के लिए; गूंज "आउटपुट: $ i"; किया हुआ

या बीएसडी सिस्टम पर jot (1) का उपयोग करें :

$ i में (jot 0 10); गूंज "आउटपुट: $ i"; किया हुआ

3
true $(( i++ ))सभी मामलों में काम नहीं करता है, इसलिए सबसे अधिक पोर्टेबल होगा true $((i=i+1))
फ्लो

अर्ध बृहदान्त्र में "के लिए नहीं आना चाहिए ((मैं = 0; मैं <अधिकतम; i ++)) ;;
लोगन

9

इसे करने का एक से अधिक तरीका है।

max=10
for i in `eval "echo {2..$max}"`
do
    echo "$i"
done

7
एक सुरक्षा जोखिम, क्योंकि आप जो कुछ भी निर्धारित evalकरेंगे उसका मूल्यांकन करेंगे । विचार करें , फिर कुछ और विनाशकारी के साथ बदलें । maxmax="2}; echo ha; #"echo ha
Chepner

6
(एस) उसने अधिकतम 10 सेट किया। कोई जोखिम नहीं।
कॉनरेड मेयर

9

यदि seqआपके सिस्टम पर कमांड उपलब्ध है:

for i in `seq 2 $max`
do
  echo "output: $i"
done

यदि नहीं, तो गरीब आदमी का उपयोग करने seqके साथ perl:

seq=`perl -e "\$,=' ';print 2..$max"`
for i in $seq
do
  echo "output: $i"
done

उन उद्धरण चिह्नों को देखें।


मैंने अभी जाँच की है कि; ऐसा नहीं लगता कि यह है।
पलक

5

यह एक तरीका है:
बैश:

max=10
for i in $(bash -c "echo {2..${max}}"); do echo $i; done

उपरोक्त बैश तरीका काम करेगा kshऔर वह zshभी, जब या क्रमशः bash -cबदल दिया जाएगा ।ksh -czsh -c

नोट: for i in {2..${max}}; do echo $i; doneमें काम करता है zshऔर ksh


4

हम C प्रोग्रामिंग की तरह लूप को पुनरावृत्त कर सकते हैं।

#!/bin/bash
for ((i=1; i<=20; i=i+1))
do 
      echo $i
done

2

यहाँ इसने Mac OS X पर काम किया।

इसमें बीएसडी तिथि का उदाहरण भी शामिल है कि किस तरह से वेतन वृद्धि और गिरावट भी होती है:

for ((i=28; i>=6 ; i--));
do
    dat=`date -v-${i}d -j "+%Y%m%d"` 
    echo $dat
done

2

ठीक है, क्योंकि मेरे पास seqमेरे सिस्टम पर मैक कमांड स्थापित नहीं है (Mac OS X v10.6.1 (स्नो लेपर्ड)), मैंने whileइसके बजाय एक लूप का उपयोग किया:

max=5
i=1

while [ $max -gt $i ]
do
    (stuff)
done

* श्रग्स * जो भी काम करता है।


2
seq अपेक्षाकृत नया है। मुझे केवल कुछ महीने पहले इसके बारे में पता चला। लेकिन आप 'लूप' के लिए इस्तेमाल कर सकते हैं !! एक 'जबकि ’का नुकसान यह है कि आपको काउंटर को लूप के अंदर कहीं और बढ़ाना पड़ता है, या फिर नीचे की ओर लूप याद रखना पड़ता है।
सिस्टम PAUSE

1

ये सभी करते हैं {1..8}और सभी को POSIX होना चाहिए। यदि आप continueलूप में एक सशर्त डालते हैं तो वे भी नहीं टूटेंगे। विहित तरीका:

f=
while [ $((f+=1)) -le 8 ]
do
  echo $f
done

दूसरा रास्ता:

g=
while
  g=${g}1
  [ ${#g} -le 8 ]
do
  echo ${#g}
done

और दुसरी:

set --
while
  set $* .
  [ ${#} -le 8 ]
do
  echo ${#}
done

1

उपयोग:

max=10
for i in `eval echo {2..$max}`
do
    echo $i
done

चर प्रतिस्थापन के बाद {} का पुनर्मूल्यांकन करने के लिए आपको स्पष्ट 'eval' कॉल की आवश्यकता है।

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