मैं कैसे बैश में चर द्वारा परिभाषित संख्याओं की संख्या पर पुनरावृति कर सकता हूं?


1541

जब मैं एक चर द्वारा रेंज दी जाती है तो मैं बैश में कितने नंबरों पर पुनरावृति कर सकता हूं?

मुझे पता है कि मैं यह कर सकता हूं (बैश प्रलेखन में "अनुक्रम अभिव्यक्ति" ):

 for i in {1..5}; do echo $i; done

जो देता है:

1
2
3
4
5

फिर भी, मैं किसी चर के साथ रेंज एंडपॉइंट की जगह कैसे ले सकता हूं? यह काम नहीं करता है:

END=5
for i in {1..$END}; do echo $i; done

कौन सा प्रिंट:

{} 1..5


26
हाय सब, मैं यहाँ पढ़ा है और संकेत सभी वास्तव में उपयोगी हैं। मुझे लगता है कि seq के उपयोग से बचना सबसे अच्छा है। कारण यह है कि कुछ स्क्रिप्ट को पोर्टेबल होने की आवश्यकता होती है और उन्हें विभिन्न प्रकार के यूनिक्स सिस्टम पर चलना चाहिए, जहां कुछ कमांड मौजूद नहीं हो सकते हैं। उदाहरण के लिए, FreeBSD सिस्टम पर डिफ़ॉल्ट रूप से seq मौजूद नहीं है।


9
मुझे याद नहीं है कि वास्तव में बैश का कौन सा संस्करण है, लेकिन यह कमांड ट्रेलिंग जीरो को भी सपोर्ट करता है। जो कभी-कभी वास्तव में मददगार होता है। कमांड for i in {01..10}; do echo $i; doneजैसे नंबर देगा 01, 02, 03, ..., 10
topr

1
मेरे जैसे उन लोगों के लिए जो सिर्फ एक सरणी के सूचकांकों की सीमा पर चलना चाहते हैं , बैश तरीका होगा: myarray=('a' 'b' 'c'); for i in ${!myarray[@]}; do echo $i; done(विस्मयादिबोधक चिह्न पर ध्यान दें)। यह मूल प्रश्न से अधिक विशिष्ट है, लेकिन मदद कर सकता है। बैश पैरामीटर विस्तार
प्लाज़्माबिन्टॉन्ग

1
ब्रेस विस्तार का उपयोग उन अभिव्यक्तियों के लिए भी किया जाता है जैसे {jpg,png,gif}कि यहां सीधे संबोधित नहीं किया गया है, हालांकि उत्तर समान होगा। चर के साथ ब्रेस विस्तार देखें ? [डुप्लिकेट] जो इस एक के डुप्लिकेट के रूप में चिह्नित है।
ट्रिपलए

जवाबों:


1741
for i in $(seq 1 $END); do echo $i; done

संपादित करें: मैं seqअन्य तरीकों से अधिक पसंद करता हूं क्योंकि मैं वास्तव में इसे याद कर सकता हूं;)


36
seq में एक बाहरी कमांड का निष्पादन शामिल है जो आमतौर पर चीजों को धीमा कर देती है। यह महत्वपूर्ण नहीं है, लेकिन यह महत्वपूर्ण हो जाता है यदि आप बहुत सारे डेटा को संभालने के लिए स्क्रिप्ट लिख रहे हैं।
paxdiablo

37
बस एक-लाइनर के लिए ठीक है। पैक्स का समाधान भी ठीक है, लेकिन अगर प्रदर्शन वास्तव में एक चिंता का विषय था, तो मैं एक शेल स्क्रिप्ट का उपयोग नहीं करूंगा।
एस्कैरसाइकल

17
नंबर उत्पन्न करने के लिए seq को केवल एक बार कहा जाता है। निष्पादित () 'आईएनजी यह महत्वपूर्ण नहीं होना चाहिए जब तक कि यह लूप किसी अन्य तंग लूप के अंदर न हो।
जेवियर

29
बाहरी आदेश वास्तव में पुनः लागू नहीं होता है: यदि आप बाहरी कमांड चलाने के ओवरहेड के बारे में चिंतित हैं, तो आप शेल स्क्रिप्ट का उपयोग बिल्कुल नहीं करना चाहते हैं, लेकिन आमतौर पर यूनिक्स पर ओवरहेड कम होता है। हालाँकि, अंत उच्च होने पर मेमोरी उपयोग का मुद्दा है।
मार्क बेकर

18
ध्यान दें कि seq $ENDयह पर्याप्त होगा, क्योंकि डिफ़ॉल्ट 1 से शुरू होना है man seq: "यदि FIRST या INCREMENT छूट गया है, तो यह 1 में चूक जाता है"।
फेडोरक्वी 'एसओ स्टॉप हर्टिंग'

469

seqविधि सरल है, लेकिन बैश में निर्मित गणित मूल्यांकन किया है।

END=5
for ((i=1;i<=END;i++)); do
    echo $i
done
# ==> outputs 1 2 3 4 5 on separate lines

for ((expr1;expr2;expr3));निर्माण सिर्फ तरह काम करता है for (expr1;expr2;expr3)सी और इसी तरह की भाषाओं में, और अन्य तरह ((expr))के मामलों में, बैश उन्हें गणित के रूप में व्यवहार करता है।


67
इस तरह एक बड़ी सूची की मेमोरी ओवरहेड, और एक निर्भरता से बचा जाता है seq। इसका इस्तेमाल करें!
बोबोगो

3
@MarinSagovac यह काम करता है और कोई सिंटैक्स त्रुटियां नहीं हैं। क्या आप सुनिश्चित हैं कि आपका शेल बैश है?
gniourf_gniourf

3
@MarinSagovac #!/bin/bashअपनी स्क्रिप्ट की पहली पंक्ति बनाना सुनिश्चित करें । wiki.ubuntu.com/…
मेलेबियस

6
उस पर बस एक छोटा सा प्रश्न: क्यों ((i = 1; मैं <= END; i ++)) और नहीं ((i = 1; मैं <= $ END; मैं ++)); $ END से पहले क्यों नहीं?
Baedsch

5
@ बेस्डच: उसी कारण से मुझे $ i के रूप में उपयोग नहीं किया जाता है। बैश मैन पेज अंकगणितीय मूल्यांकन के लिए बताता है: "एक अभिव्यक्ति के भीतर, शेल चर भी पैरामीटर विस्तार वाक्यविन्यास का उपयोग किए बिना नाम से संदर्भित किया जा सकता है।"
user3188140

192

विचार-विमर्श

seqजियारो ने सुझाव दिया कि इसका उपयोग करना ठीक है। पैक्स डियाब्लो ने एक बैश लूप का सुझाव दिया कि एक सबप्रोसेस को कॉल करने से बचने के लिए, अधिक मेमोरी फ्रेंडली होने का अतिरिक्त लाभ अगर $ END बहुत बड़ा है। ज़थ्रस ने लूप के कार्यान्वयन में एक विशिष्ट बग देखा, और यह भी संकेत दिया कि चूंकि iएक पाठ चर है, इसलिए एक धीमी गति से डाउन के साथ निरंतर रूपांतरण टू-एंड-फ्रो नंबर किए जाते हैं।

पूर्णांक अंकगणित

यह बैश लूप का बेहतर संस्करण है:

typeset -i i END
let END=5 i=1
while ((i<=END)); do
    echo $i
    
    let i++
done

यदि केवल एक चीज जो हम चाहते हैं वह है echo, तो हम लिख सकते हैं echo $((i++))

ephemient ने मुझे कुछ सिखाया: बैश for ((expr;expr;expr))कंस्ट्रक्शन की अनुमति देता है । चूँकि मैंने बैश के लिए पूरे मैन पेज को कभी नहीं पढ़ा है (जैसे मैंने कोर्न शेल ( kshमैन पेज के साथ किया है ), और यह बहुत समय पहले था), मुझे याद आया।

इसलिए,

typeset -i i END # Let's be explicit
for ((i=1;i<=END;++i)); do echo $i; done

लगता है कि सबसे अधिक मेमोरी-कुशल तरीका है (यह आवश्यक नहीं होगा कि मेमोरी का seqउत्पादन करने के लिए मेमोरी आवंटित की जाए , जो कि एक समस्या हो सकती है यदि END बहुत बड़ी है), हालांकि शायद "सबसे तेज़" नहीं है।

प्रारंभिक प्रश्न

eschercycle ने कहा कि { a .. b } बैश नोटेशन केवल शाब्दिक के साथ काम करता है; सच है, बैश मैनुअल के अनुसार। एक के fork()बिना एक (आंतरिक) के साथ इस बाधा को दूर कर सकते हैं exec()(जैसा कि कॉलिंग के मामले में है seq, जो एक और छवि होने के लिए एक कांटा + निष्पादन की आवश्यकता है):

for i in $(eval echo "{1..$END}"); do

दोनों evalऔर echoबैश builtins रहे हैं, लेकिन एक fork()आदेश प्रतिस्थापन (के लिए आवश्यक है $(…)निर्माण)।


1
सी स्टाइल लूप के लिए एकमात्र दोष यह है कि यह कमांड लाइन तर्कों का उपयोग नहीं कर सकता है, क्योंकि वे "$" से शुरू होते हैं।
karatedog

3
@karatedog: for ((i=$1;i<=$2;++i)); do echo $i; doneस्क्रिप्ट में bash v.4.1.9 पर मेरे लिए ठीक काम करता है, इसलिए मुझे कमांड लाइन के तर्कों के साथ कोई समस्या नहीं दिखती है। क्या आपका मतलब कुछ और है?
तीतोट

ऐसा लगता है कि eval solution C के लिए निर्मित की तुलना में तेज है: $ time for ((i = 1; i <= 100000; ++ i)); करना :; किया वास्तविक 0m21.220s उपयोगकर्ता 0m19.763s sys 0m1.203s $ i में $ के लिए $ समय (eval echo "{1..100000}"); करना :; किया हुआ; असली 0m13.881s उपयोगकर्ता 0m13.536s sys 0m0.152s
Marcin Zaluski

3
बेनाम: हाँ, लेकिन eval बुराई है ... @MarcinZaluski time for i in $(seq 100000); do :; doneबहुत तेज है!
एफ। हौरी

निष्कासन संस्करण मेरी मशीन पर सबसे तेज़ होने के बाद से प्रदर्शन विशिष्ट होना चाहिए।
एंड्रयू प्रॉक

102

यहाँ क्यों मूल अभिव्यक्ति काम नहीं किया।

से आदमी पार्टी :

ब्रेस विस्तार किसी भी अन्य विस्तार से पहले किया जाता है, और परिणाम में अन्य विस्तार के लिए विशेष किसी भी वर्ण संरक्षित हैं। यह सख्ती से पाठ्य है। बैश ब्रेसिज़ के बीच विस्तार या पाठ के संदर्भ में किसी भी व्याख्यात्मक व्याख्या को लागू नहीं करता है।

इसलिए, ब्रेस विस्तार पैरामीटर विस्तार से पहले, विशुद्ध रूप से एक टेक्स्ट मैक्रो ऑपरेशन के रूप में जल्दी किया जाता है

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

सिफ़ारिश करना

मैं Posix 1 सुविधाओं के साथ चिपके रहने का सुझाव दूंगा । इसका मतलब है for i in <list>; do, यदि सूची पहले से ही ज्ञात है, तो उपयोग करना , अन्यथा, उपयोग whileया seq, जैसा कि:

#!/bin/sh

limit=4

i=1; while [ $i -le $limit ]; do
  echo $i
  i=$(($i + 1))
done
# Or -----------------------
for i in $(seq 1 $limit); do
  echo $i
done


1. बैश एक बेहतरीन शेल है और मैं इसका इस्तेमाल अंतःक्रियात्मक रूप से करता हूं, लेकिन मैं अपनी स्क्रिप्ट में बैश-आइसम नहीं डालता। लिपियों को तेज शेल, अधिक सुरक्षित, अधिक एम्बेडेड-स्टाइल वाले की आवश्यकता हो सकती है। उन्हें जो कुछ भी / बिन / श के रूप में स्थापित है, उस पर चलने की आवश्यकता हो सकती है, और फिर सभी सामान्य समर्थक मानक तर्क हैं। शेलशॉक , उर्फ बाशडोर याद है ?


13
मेरे पास शक्ति नहीं है, लेकिन मैं इस सूची को थोड़ा-बहुत ऊपर ले जाऊंगा, सभी बैश नाभि-ऊपर की ओर, लेकिन लूप और अंकगणितीय मूल्यांकन के लिए सी-स्टाइल के तुरंत बाद।
18

2
एक निहितार्थ यह है कि ब्रेस विस्तार seqबड़ी श्रृंखलाओं की तुलना में बहुत अधिक मेमोरी को नहीं बचाता है। जैसे, echo {1..1000000} | wcपता चलता है कि प्रतिध्वनि 1 लाइन, एक मिलियन शब्द और 6,888,896 बाइट्स का उत्पादन करती है। seq 1 1000000 | wcएक लाख लाइन, एक लाख शब्द और 6,888,896 बाइट्स देने की कोशिश कर रहा है और यह भी सात गुना से अधिक तेज है, जैसा कि timeकमांड द्वारा मापा गया है ।
जॉर्ज

नोट: मैंने whileअपने जवाब में पहले POSIX विधि का उल्लेख किया था : stackoverflow.com/a/31365662/895245 लेकिन खुशी है कि आप सहमत हैं :-)
Ciro Santilli 冠状 the 六四 事件

मैंने अपने प्रदर्शन तुलनात्मक उत्तर में इस उत्तर को नीचे शामिल किया है। stackoverflow.com/a/54770805/117471 (यह मेरे लिए एक नोट है कि मैं किन लोगों को करने के लिए छोड़ दिया है।)
ब्रूनो ब्रोंस्की

@मेटोर ने सोचा कि लूप और अंकगणितीय मूल्यांकन के लिए सी-स्टाइल एक ही समाधान है। क्या मैं कुछ भूल रहा हूँ?
ऑस्कर जांग

71

POSIX रास्ता

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

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

आउटपुट:

2
3
4
5

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


इस उत्तर पर बस 4 अपवोट थे, जो कि बहुत ही असामान्य है। यदि यह कुछ लिंक एकत्रीकरण वेबसाइट पर पोस्ट किया गया था, तो कृपया मुझे एक लिंक दें, चीयर्स।
सिरो सेंटिल्ली 冠状 i i i ''

उद्धरण को संदर्भित करता है x, संपूर्ण अभिव्यक्ति को नहीं। $((x + 1))बस ठीक है।
चेप्टर

पोर्टेबल नहीं है, और GNU से अलग है seq(BSD seqआपको अनुक्रम समाप्ति स्ट्रिंग सेट करने की अनुमति देता है -t), FreeBSD और NetBSD भी seqक्रमशः 9.0 और 3.0 के बाद से है।
एड्रियन गुंटर

@CiroSantilli @chepner $((x+1))और $((x + 1))पार्स बिल्कुल वैसा ही है, जब पार्सर tokenizes के रूप में x+1यह 3 टोकन में विभाजित किया जाएगा: x, +, और 1xएक मान्य संख्यात्मक टोकन नहीं है, लेकिन यह एक मान्य चर नाम टोकन है, फिर x+भी विभाजित नहीं है। +एक मान्य अंकगणितीय ऑपरेटर टोकन है, फिर +1भी नहीं है, इसलिए टोकन फिर से वहां विभाजित हो गया है। इत्यादि।
एड्रियन गुंटर

मैंने अपने प्रदर्शन तुलनात्मक उत्तर में इस उत्तर को नीचे शामिल किया है। stackoverflow.com/a/54770805/117471 (यह मेरे लिए एक नोट है कि मैं किन लोगों को करने के लिए छोड़ दिया है।)
ब्रूनो ब्रोंस्की

35

अप्रत्यक्ष की एक और परत:

for i in $(eval echo {1..$END}); do
    

2
+1: इसके अलावा, 'i in {1 ..' $ END '} के लिए; करते हैं ... 'इस मुद्दे को हल करने का स्वाभाविक तरीका लगता है।
विलियम पर्ससेल

28

आप उपयोग कर सकते हैं

for i in $(seq $END); do echo $i; done

seq में एक बाहरी कमांड का निष्पादन शामिल है जो आमतौर पर चीजों को धीमा कर देती है।
paxdiablo

9
इसमें सिर्फ एक बार, प्रत्येक पुनरावृत्ति के लिए एक बाहरी कमांड का निष्पादन शामिल नहीं है। यदि एक बाहरी कमांड लॉन्च करने का समय एक समस्या है, तो आप गलत भाषा का उपयोग कर रहे हैं।
मार्क बेकर

1
तो केवल एक ही मामला है जहां यह मायने रखता है? मैं सोच रहा था कि क्या कोई प्रदर्शन अंतर था, या कुछ अज्ञात तकनीकी दुष्प्रभाव?
19

@Squeaky यह एक अलग सवाल है जिसका जवाब यहाँ दिया गया है: stackoverflow.com/questions/4708549/…
tripleee

मैंने अपने प्रदर्शन तुलनात्मक उत्तर में इस उत्तर को नीचे शामिल किया है। stackoverflow.com/a/54770805/117471 (यह मेरे लिए एक नोट है कि मैं किन लोगों को करने के लिए छोड़ दिया है।)
ब्रूनो ब्रोंस्की

21

यदि आपको इसकी आवश्यकता उपसर्ग से है तो आप इसे पसंद कर सकते हैं

 for ((i=7;i<=12;i++)); do echo `printf "%2.0d\n" $i |sed "s/ /0/"`;done

वह उपज देगा

07
08
09
10
11
12

4
printf "%02d\n" $iसे आसान नहीं होगा printf "%2.0d\n" $i |sed "s/ /0/"?
zb226

19

यदि आप BSD / OS X पर हैं, तो आप seq के बजाय jot का उपयोग कर सकते हैं:

for i in $(jot $END); do echo $i; done

17

यह ठीक काम करता है bash:

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

6
echo $((i++))काम करता है और इसे एक पंक्ति में जोड़ता है।
ब्रूनो ब्रोंस्की

1
इसमें बेस्ड एक्सटेंशन हैं। POSIX संस्करण: stackoverflow.com/a/31365662/895245
Ciro Santilli 审查::: 事件 法轮功

1
@Ciro, चूँकि सवाल विशेष रूप से bash का है, और एक bash टैग है, मुझे लगता है कि आप शायद पाएंगे कि bash 'एक्सटेंशन' ठीक ठाक से अधिक हैं :-)
paxdiablo

@paxdiablo मेरा मतलब यह नहीं है कि यह सही नहीं है, लेकिन जब हम कर सकते हैं तो पोर्टेबल क्यों न हो ;-)
सिरो सेंटिल्ली 审查 lo lo lo

में bash, हम बस कर सकते हैं while [[ i++ -le "$END" ]]; doपरीक्षण में (पोस्ट) वेतन वृद्धि करने के लिए
हारून McDaid

14

मैंने यहां कुछ विचारों को संयोजित किया है और प्रदर्शन को मापा है।

TL, डॉ। Takeaways:

  1. seqऔर {..}वास्तव में तेज हैं
  2. forऔर whileलूप्स धीमे हैं
  3. $( ) धीमा है
  4. for (( ; ; )) लूप धीमे होते हैं
  5. $(( )) और भी धीमा है
  6. स्मृति में N संख्याओं के बारे में चिंता करना (seq या {..}) मूर्खतापूर्ण है (कम से कम 1 मिलियन तक)।

ये निष्कर्ष नहीं हैं । आपको निष्कर्ष निकालने के लिए इनमें से प्रत्येक के पीछे C कोड को देखना होगा। यह इस बारे में अधिक है कि हम कोड में लूपिंग के लिए इनमें से प्रत्येक तंत्र का उपयोग कैसे करते हैं। अधिकांश एकल ऑपरेशन एक ही गति होने के काफी करीब हैं कि यह ज्यादातर मामलों में मायने नहीं रखता है। लेकिन एक तंत्र जैसा for (( i=1; i<=1000000; i++ ))कई ऑपरेशन है जैसा कि आप नेत्रहीन देख सकते हैं। यह आपके द्वारा प्राप्त किए गए प्रति लूप के कई और ऑपरेशन भी हैं for i in $(seq 1 1000000)। और यह आपके लिए स्पष्ट नहीं हो सकता है, यही कारण है कि इस तरह परीक्षण करना मूल्यवान है।

क़ौम

# show that seq is fast
$ time (seq 1 1000000 | wc)
 1000000 1000000 6888894

real    0m0.227s
user    0m0.239s
sys     0m0.008s

# show that {..} is fast
$ time (echo {1..1000000} | wc)
       1 1000000 6888896

real    0m1.778s
user    0m1.735s
sys     0m0.072s

# Show that for loops (even with a : noop) are slow
$ time (for i in {1..1000000} ; do :; done | wc)
       0       0       0

real    0m3.642s
user    0m3.582s
sys 0m0.057s

# show that echo is slow
$ time (for i in {1..1000000} ; do echo $i; done | wc)
 1000000 1000000 6888896

real    0m7.480s
user    0m6.803s
sys     0m2.580s

$ time (for i in $(seq 1 1000000) ; do echo $i; done | wc)
 1000000 1000000 6888894

real    0m7.029s
user    0m6.335s
sys     0m2.666s

# show that C-style for loops are slower
$ time (for (( i=1; i<=1000000; i++ )) ; do echo $i; done | wc)
 1000000 1000000 6888896

real    0m12.391s
user    0m11.069s
sys     0m3.437s

# show that arithmetic expansion is even slower
$ time (i=1; e=1000000; while [ $i -le $e ]; do echo $i; i=$(($i+1)); done | wc)
 1000000 1000000 6888896

real    0m19.696s
user    0m18.017s
sys     0m3.806s

$ time (i=1; e=1000000; while [ $i -le $e ]; do echo $i; ((i=i+1)); done | wc)
 1000000 1000000 6888896

real    0m18.629s
user    0m16.843s
sys     0m3.936s

$ time (i=1; e=1000000; while [ $i -le $e ]; do echo $((i++)); done | wc)
 1000000 1000000 6888896

real    0m17.012s
user    0m15.319s
sys     0m3.906s

# even a noop is slow
$ time (i=1; e=1000000; while [ $((i++)) -le $e ]; do :; done | wc)
       0       0       0

real    0m12.679s
user    0m11.658s
sys 0m1.004s

1
अच्छा! हालांकि अपने सारांश से सहमत नहीं हैं। मुझे लगता है कि जैसे $(seq)ही गति के बारे में है {a..b}। इसके अलावा, प्रत्येक ऑपरेशन में एक ही समय लगता है, इसलिए मेरे लिए लूप के प्रत्येक पुनरावृत्ति में लगभग 4μs जोड़ता है। यहाँ एक ऑपरेशन शरीर में एक प्रतिध्वनि है, एक अंकगणित की तुलना, एक वृद्धि आदि, क्या यह आश्चर्य की बात है? कौन परवाह करता है कि लूप पैराफर्नेलिया को अपना काम करने में कितना समय लगता है - लूप की सामग्री पर रनटाइम का प्रभुत्व होने की संभावना है।
बॉबबोगो

@bobogo आप सही हैं, यह वास्तव में ऑपरेशन की गिनती के बारे में है। मैंने इसे दर्शाने के लिए अपना उत्तर अपडेट किया। कई कॉल हम वास्तव में उम्मीद से अधिक संचालन करते हैं। मैंने इसे लगभग 50 परीक्षणों की एक सूची से नीचे सीमित कर दिया, जो मैंने चलाए। मुझे उम्मीद थी कि इस भीड़ के लिए भी मेरा शोध बहुत नीरस था। हमेशा की तरह, मैं आपके कोडिंग प्रयासों को प्राथमिकता देने का सुझाव देता हूं जैसे: इसे कम करें; इसे पठनीय बनाओ; इसे तेज गति से करें; इसे पोर्टेबल बनाएं। अक्सर # 1 कारण # 3। # 4 पर अपना समय बर्बाद मत करो जब तक आप चाहिए।
ब्रूनो ब्रोंस्की

8

मुझे पता है कि यह सवाल क्या है bash, लेकिन - सिर्फ रिकॉर्ड के लिए - ksh93होशियार है और उम्मीद के मुताबिक इसे लागू करता है:

$ ksh -c 'i=5; for x in {1..$i}; do echo "$x"; done'
1
2
3
4
5
$ ksh -c 'echo $KSH_VERSION'
Version JM 93u+ 2012-02-29

$ bash -c 'i=5; for x in {1..$i}; do echo "$x"; done'
{1..5}

8

यह एक और तरीका है:

end=5
for i in $(bash -c "echo {1..${end}}"); do echo $i; done

1
यह एक और खोल spawning के उपरि है।
कोडफ़ेस्टर

1
वास्तव में, यह अतिरिक्त भयानक है क्योंकि यह 2 गोले पैदा करता है जब 1 पर्याप्त होगा।
ब्रूनो ब्रोंस्की

8

यदि आप ब्रेस-एक्सप्रेशन सिंटैक्स के जितना संभव हो उतना करीब रहना चाहते हैं, तो rangeफ़ंक्शन को बैश-ट्रिक सेrange.bash बाहर निकालें '

उदाहरण के लिए, निम्न में से सभी एक ही कार्य करेंगे echo {1..10}:

source range.bash
one=1
ten=10

range {$one..$ten}
range $one $ten
range {1..$ten}
range {1..10}

यह संभव के रूप में कुछ "gotchas" के साथ देशी बैश सिंटैक्स का समर्थन करने की कोशिश करता है: न केवल चर का समर्थन किया जाता है, लेकिन अक्सर-अवांछनीय व्यवहारों को स्ट्रिंग के रूप में आपूर्ति की जा रही है (जैसे for i in {1..a}; do echo $i; done)।

अन्य उत्तर ज्यादातर मामलों में काम करेंगे, लेकिन उन सभी में कम से कम एक कमियां हैं:

  • उनमें से कई उप-भाग का उपयोग करते हैं , जो प्रदर्शन को नुकसान पहुंचा सकते हैं और कुछ प्रणालियों पर संभव नहीं हो सकता है
  • उनमें से कई बाहरी कार्यक्रमों पर भरोसा करते हैं। यहां तक seqकि एक द्विआधारी है जिसे उपयोग करने के लिए स्थापित किया जाना चाहिए, बैश द्वारा लोड किया जाना चाहिए, और इसमें वह प्रोग्राम होना चाहिए, जिसके लिए आपको इस मामले में काम करना है। सर्वव्यापी या नहीं, यह केवल बैश भाषा की तुलना में बहुत अधिक निर्भर है।
  • समाधान जो केवल मूल बैश कार्यक्षमता का उपयोग करते हैं, जैसे @ ephemient's, अल्फ़ाबेटिक रेंज पर काम नहीं करेंगे, जैसे {a..z}; ब्रेस विस्तार होगा। सवाल संख्याओं की सीमाओं के बारे में था , हालांकि, यह एक वक्रोक्ति है।
  • उनमें से ज्यादातर नेत्रहीन {1..10}ब्रेस-विस्तारित सीमा सिंटैक्स के समान नहीं हैं , इसलिए ऐसे प्रोग्राम जो दोनों का उपयोग करते हैं, वे पढ़ने में थोड़ा कठिन हो सकते हैं।
  • @ बोब्बोगो के जवाब में कुछ परिचित वाक्यविन्यास का उपयोग किया गया है, लेकिन कुछ अप्रत्याशित होता है यदि $ENDचर रेंज के दूसरी ओर के लिए मान्य श्रेणी "बुकेंड" नहीं है। अगरEND=a , उदाहरण के लिए, एक त्रुटि नहीं होगी और शब्दशः मूल्य {1..a}प्रतिध्वनित होगा। यह बैश का डिफ़ॉल्ट व्यवहार है, साथ ही - यह अक्सर अप्रत्याशित होता है।

अस्वीकरण: मैं लिंक किए गए कोड का लेखक हूं।


7

इसके {}साथ बदलें (( )):

tmpstart=0;
tmpend=4;

for (( i=$tmpstart; i<=$tmpend; i++ )) ; do 
echo $i ;
done

पैदावार:

0
1
2
3
4

मैंने अपने प्रदर्शन तुलनात्मक उत्तर में इस उत्तर को नीचे शामिल किया है। stackoverflow.com/a/54770805/117471 (यह मेरे लिए एक नोट है कि जो मैंने करने के लिए छोड़ दिया है, उस पर नज़र रखने के लिए।)
ब्रूनो ब्रोंस्की

6

ये सभी अच्छे हैं, लेकिन seq माना जाता है कि यह केवल पदावनत है और अधिकांश केवल न्यूमेरिक रेंज के साथ काम करते हैं।

यदि आप दोहरे उद्धरण चिह्नों में अपने लूप के लिए संलग्न करते हैं, तो स्टार्ट और एंड वेरिएबल्स को स्ट्रिंग को प्रतिध्वनित करने पर निष्क्रिय कर दिया जाएगा, और आप स्ट्रिंग को वापस BASH करने के लिए शिप कर सकते हैं। $iजरूरत है इसलिए इसे उपधारा में भेजे जाने से पहले मूल्यांकन नहीं किया जाता है।

RANGE_START=a
RANGE_END=z
echo -e "for i in {$RANGE_START..$RANGE_END}; do echo \\${i}; done" | bash

यह आउटपुट एक चर को भी सौंपा जा सकता है:

VAR=`echo -e "for i in {$RANGE_START..$RANGE_END}; do echo \\${i}; done" | bash`

एकमात्र "ओवरहेड" यह उत्पन्न करना चाहिए बैश का दूसरा उदाहरण होना चाहिए ताकि यह गहन संचालन के लिए उपयुक्त हो।


5

यदि आप शेल कमांड कर रहे हैं और आपको (जैसे मुझे) पाइपलाइनिंग के लिए एक बुत है, तो यह अच्छा है:

seq 1 $END | xargs -I {} echo {}


3

ऐसा करने के कई तरीके हैं, हालांकि जो मैं पसंद करता हूं वह नीचे दिया गया है

का उपयोग करते हुए seq

से पर्यायवाची man seq

$ seq [-w] [-f format] [-s string] [-t string] [first [incr]] last

वाक्य - विन्यास

पूर्ण कमान
seq first incr last

  • पहले क्रम में संख्या शुरू कर रहा है [डिफ़ॉल्ट रूप से वैकल्पिक है: 1]
  • वेतन वृद्धि है [वैकल्पिक रूप से, डिफ़ॉल्ट रूप से: 1]
  • अंतिम क्रम में अंतिम संख्या है

उदाहरण:

$ seq 1 2 10
1 3 5 7 9

केवल पहले और अंतिम के साथ:

$ seq 1 5
1 2 3 4 5

केवल अंतिम के साथ:

$ seq 5
1 2 3 4 5

का उपयोग करते हुए {first..last..incr}

यहाँ पहले और अंतिम अनिवार्य हैं और incr वैकल्पिक है

सिर्फ पहले और आखिरी का उपयोग करना

$ echo {1..5}
1 2 3 4 5

इंक का उपयोग करना

$ echo {1..10..2}
1 3 5 7 9

आप इसका उपयोग नीचे दिए गए वर्णों के लिए भी कर सकते हैं

$ echo {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

3

अगर आप ' seq' या ' eval' jotया अंकगणितीय विस्तार प्रारूप का उपयोग नहीं करना चाहते हैं । for ((i=1;i<=END;i++)), या अन्य छोरों उदा। while, और आप केवल printf' echo' ' ' और ' ' खुश ' ' नहीं चाहते , तो यह सरल उपाय आपके बजट में फिट हो सकते हैं:

a=1; b=5; d='for i in {'$a'..'$b'}; do echo -n "$i"; done;' echo "$d" | bash

पुनश्च: मेरे बैश में seqवैसे भी ' ' कमांड नहीं है।

मैक OSX 10.6.8, बैश 3.2.48 पर परीक्षण किया गया


0

यह बाश और कॉर्न में काम करता है, उच्च से निम्न संख्या में भी जा सकता है। शायद सबसे तेज़ या सुंदर नहीं है, लेकिन यह काफी अच्छी तरह से काम करता है। निगेटिव भी संभालती है।

function num_range {
   # Return a range of whole numbers from beginning value to ending value.
   # >>> num_range start end
   # start: Whole number to start with.
   # end: Whole number to end with.
   typeset s e v
   s=${1}
   e=${2}
   if (( ${e} >= ${s} )); then
      v=${s}
      while (( ${v} <= ${e} )); do
         echo ${v}
         ((v=v+1))
      done
   elif (( ${e} < ${s} )); then
      v=${s}
      while (( ${v} >= ${e} )); do
         echo ${v}
         ((v=v-1))
      done
   fi
}

function test_num_range {
   num_range 1 3 | egrep "1|2|3" | assert_lc 3
   num_range 1 3 | head -1 | assert_eq 1
   num_range -1 1 | head -1 | assert_eq "-1"
   num_range 3 1 | egrep "1|2|3" | assert_lc 3
   num_range 3 1 | head -1 | assert_eq 3
   num_range 1 -1 | tail -1 | assert_eq "-1"
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.