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


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.