बैश में, लूप के लिए लूप नियंत्रण में पूर्णांक चर का उपयोग करना संभव है?


65

मेरे पास निम्नलिखित बैश स्क्रिप्ट है:

#!/bin/bash

upperlim=10

for i in {0..10}
do
echo $i
done

for i in {0..$upperlim}
do
echo $i
done

पहला forलूप ( लूप नियंत्रण में चर के बिनाupperlim ) ठीक काम करता है, लेकिन दूसरा forलूप ( लूप नियंत्रण में चर के साथupperlim ) नहीं करता है। क्या कोई तरीका है कि मैं दूसरे forलूप को संशोधित कर सकता हूं ताकि यह काम करे? आपके समय के लिए धन्यवाद।


4
एचएम, यहां तक ​​कि for i in {0..$((upperlim))}; do echo $i; doneकाम नहीं करता है
— बोन्सी स्कॉट

और +1 क्योंकि मुझे वह व्यवहार दिलचस्प लगता है
— बोन्सी स्कॉट

की संभावित क्रॉस साइट डुप्लिकेट: stackoverflow.com/questions/169511/…
— Ciro Santilli 新疆:::

एक बाहरी लिंक जो इसका उत्तर देता है: cyberciti.biz/faq/…
— kon psych

जवाबों:


62

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

upperlim=10

for ((i=0; i<=upperlim; i++)); do
   echo "$i"
done

1
और के लिए काम करता zshहै (लेकिन के लिए नहीं के रूप में अच्छी तरह से csh, tcsh)।
— गणित

29

अपनी शैली में इसे पूरा करने के लिए कुछ भी नहीं बनाया गया है, लेकिन आपको इसका उपयोग करना होगा:

d=12

for i in `eval echo {0..$d}`
do
echo $i
done

लेकिन इसके साथ seq:

lowerlimit=0
upperlimit=12

for i in $(seq $lowerlimit $upperlimit)
do
echo $i
done

व्यक्तिगत रूप से मैं seqअधिक पठनीय होने का उपयोग करता हूं ।


"बिल्ट-इन" के लिए? seqएक बाहरी आदेश है और हर जगह उपलब्ध नहीं है।
— जोर्डनम

9
@ जोर्डनम: बैश वाले सभी बिलिन का उपयोग करने के लिए। फिर मैंने कहा "लेकिन साथ seq", यह स्वीकार करते हुए कि यह बिल्ट-इन नहीं है।
— जोडी सी

तथ्य यह है कि ब्रेस विस्तार बिलिन है यहां समस्या नहीं है। readउदाहरण के लिए एक बिलिन है, लेकिन इसका कोई कारण नहीं evalहै।
— जोर्डनम

1
बिल्‍डिंग में समस्‍या नहीं है। मैं पूछने वाले के लिए एक ऑल-बैश समाधान प्रदान करना चाहता था। यदि आप इस बारे में बहस करना चाहते हैं, तो इसे चैट पर ले जाएं; इस तरह की बात के लिए टिप्पणियां अच्छी नहीं हैं
— जोड़ी सी

8

POSIX रास्ता

यदि आप पोर्टेबिलिटी की परवाह करते हैं, तो POSIX मानक से उदाहरण का उपयोग करें :

i=2
END=5
while [ $i -le $END ]; do
    echo $i
    i=$(($i+1))
done

आउटपुट:

2
3
4
5

जो चीजें POSIX नहीं हैं :

  • (( ))डॉलर के बिना, हालांकि यह POSIX द्वारा उल्लिखित एक सामान्य विस्तार है ।
  • [[। [यहाँ पर्याप्त है इसे भी देखें: https://stackoverflow.com/questions/13542832/bash-if-difference-between-square-brackets-and-double-square-brackets
  • for ((;;))
  • seq
  • {start..end}, और जो बाश मैनुअल द्वारा उल्लिखित चर के साथ काम नहीं कर सकता है ।
  • let i=i+1: POSIX 7 2. शेल कमांड भाषा में शब्द शामिल नहीं है let, और यह bash --posix4.3.42 पर विफल रहता है
  • डॉलर की i=$i+1आवश्यकता हो सकती है, लेकिन मुझे यकीन नहीं है। POSIX 7 2.6.4 अंकगणितीय विस्तार कहता है:

    यदि शेल चर x में एक मान होता है जो एक वैध पूर्णांक स्थिरांक बनाता है, वैकल्पिक रूप से एक अग्रणी प्लस या माइनस चिह्न सहित, तो अंकगणित विस्तार "$((x))"और "$(($x))"उसी मूल्य को वापस करेगा।

    लेकिन इसे पढ़ने सचमुच कि संकेत नहीं करता है कि $((x+1))फैलता है के बाद से x+1एक चर नहीं है।


1

आपका दृष्टिकोण काम नहीं करेगा क्योंकि बैश ब्रेस-विस्तार पैरामीटर विस्तार से पहले होता है। आपको पहले चर का विस्तार करने की आवश्यकता है।

आप eval के साथ काम कर सकते हैं :

upperlim=10
eval '
        for i in {0..'"$upperlim"'}
        do
                echo $i
        done
'

लूप के साथ :

upperlim=10
#with while
start=0
while [[ $start -le $upperlim ]]
do
    echo "$start"
    ((start = start + 1))
done

इसके अलावा आप इसे seq कमांड से कर सकते हैं :

upperlim=10
#seq
for i in $(seq "$upperlim"); do
  echo "$i"
done

यदि आप अपने साथ भागना चाहते हैं तो आपको for i in {0..$upperlim}कॉर्नशेल का उपयोग करना होगा। उदाहरण के लिए:

#!/bin/ksh
upperlim=10

for i in {0..$upperlim}
do
        echo $i
done
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.