लू

लूपिंग में Bash

{one: "1 अभ्यास", other: "%{count} अभ्यास"}

लूपिंग के बारे में

Bash में लूप करने के दो तरीके हैं:

  • आइटम की सूची के हर आइटम के लिए कुछ कमांड दोहराना,
  • कुछ कमांड जब तक कोई शर्त सही (या गलत) हो तब तक दोहराना।

for लूप

आइटम की किसी सूची पर इटरेशन करने के लिए हम for लूप का उपयोग करते हैं।

for varname in words; do COMMANDS; done

words को वर्ड स्प्लिटिंग और फाइलनेम एक्सपैंशन की मदद से एक्सपैंड किया जाता है (जिसके बारे में हमने Quoting कॉन्सेप्ट में सीखा था)। बारी-बारी से हर शब्द varname में असाइन किया जाता है, और COMMANDS चलाए जाते हैं।

यहाँ कुछ उदाहरण दिए गए हैं जो दिखाते हैं कि for लूप कब काम आ सकता है

  • फाइलों के एक समूह पर कुछ कमांड चलाना।

    # source all the bash library files in the current directory
    for file in ./*.bash; do
        source "$file"
    done
    
  • किसी स्क्रिप्ट या फंक्शन के हर पैरामीटर पर कुछ कमांड चलाना।

    for arg in "$@"; do
        echo "argument: ${arg}"
    done
    
  • किसी कमांड के आउटपुट में व्हाइटस्पेस से अलग किए गए हर शब्द के लिए कुछ कमांड चलाना।

    for i in $(seq 10); do
        echo "${i} squared is $((i * i))"
    done
    

    इस तरीके के बारे में कुछ चेतावनियाँ हम आगे देखेंगे।

अंकगणितीय for लूप

Bash में अंकगणितीय लूप भी होता है। यह दूसरी प्रोग्रामिंग भाषाओं से थोड़ा-बहुत परिचित लगेगा।

for ((INITIALIZATION; CONDITION; INCREMENT)); do COMMANDS; done

Bash में दोहरे ब्रैकेट अंकगणितीय संदर्भ दर्शाते हैं (Bash के अंकगणित के बारे में हम आगे किसी कॉन्सेप्ट में और देखेंगे)। seq वाला ऊपर का उदाहरण ऐसे लिखा जा सकता है

for ((i = 1; i <= 10; i++)); do
    echo "${i} squared is $((i * i))"
done

for का उपयोग कब न करें

for से लाइनें न पढ़ें।

यह एक ऐसा एंटी-पैटर्न है जो आप अक्सर देखेंगे: cat के आउटपुट पर इटरेशन करना।

for line in $(cat some.file); do 
    do_something_with "$line"
done

यह दो कारणों से गलत है।

  1. कमांड सब्स्टिट्यूशन बिना कोट्स के है, इसलिए यह वर्ड स्प्लिटिंग के अधीन होता है। वर्ड स्प्लिटिंग डिफ़ॉल्ट रूप से सिर्फ नई लाइनों पर नहीं, बल्कि व्हाइटस्पेस पर भी बाँटता है। यह for लूप फाइल की लाइनों पर नहीं, बल्कि फाइल के शब्दों पर इटरेशन कर रहा है।
  2. कमांड सब्स्टिट्यूशन बिना कोट्स के है, इसलिए यह फाइलनेम एक्सपैंशन के अधीन होता है। फाइल का हर शब्द एक ग्लॉब पैटर्न के रूप में मैच किया जाएगा।

जैसा कि हमने Quoting कॉन्सेप्ट में सीखा, वर्ड स्प्लिटिंग को IFS वेरिएबल से नियंत्रित किया जा सकता है, और फाइलनेम एक्सपैंशन को बंद किया जा सकता है। लेकिन यह एक नाज़ुक हल होता है। किसी फाइल की लाइनों पर इटरेशन करने के लिए for गलत तरीका है। फाइल पढ़ने का स्वाभाविक तरीका while लूप है।

while लूप

कुछ शर्त के सही रहने तक कमांड के एक क्रम को दोहराने के लिए while का उपयोग कीजिए।

while CONDITION_COMMANDS; do COMMANDS; done

जैसे if के साथ होता है (जैसा कि हमने Conditionals कॉन्सेप्ट में सीखा), CONDITION_COMMANDS के लिए कोई खास सिंटैक्स नहीं होता। कमांड सूची का एग्ज़िट स्टेटस तय करेगा कि यह "सही" है या "गलत"।

लूप को नियंत्रित करना

break कमांड लूप से बाहर निकाल देता है। लूप के done टर्मिनेटर के बाद वाले कमांड से कंट्रोल फिर शुरू हो जाता है।

continue कमांड लूप के अगले इटरेशन पर पहुँचा देता है।

फाइल की लाइनें पढ़ना

जैसा कि बताया गया, फाइल पढ़ने का स्वाभाविक तरीका while लूप है।

while IFS= read -r line; do
    do_something_with "$line"
done < some.file
  • फाइल की सामग्री < रीडायरेक्शन के ज़रिए लूप को इनपुट के रूप में दी जाती है।

  • read कमांड "सही" लौटाता है अगर वह अपने इनपुट से पूरी लाइन पढ़ पाता है। जब इनपुट खत्म हो जाता है, या अगर आखिरी लाइन बिना किसी नई लाइन के खत्म होती है, तो read "गलत" लौटाता है।

    • फाइल की लाइनें पढ़ने का वाकई स्वाभाविक तरीका, भले ही आखिरी लाइन नई लाइन पर खत्म न हो, यह है

      while IFS= read -r line || [[ -n "$line" ]]; do ...
      
  • -r ऑप्शन read को बताता है कि बैकस्लैश सीक्वेंस को बदलना नहीं है: बैकस्लैश सिर्फ एक आम अक्षर है।

  • IFS= खाली स्ट्रिंग को IFS में सिर्फ read कमांड की अवधि के लिए असाइन करता है। यह अस्थायी रूप से वर्ड स्प्लिटिंग बंद कर देता है, ताकि आने वाली टेक्स्ट लाइन में शुरू या आखिर में जो भी व्हाइटस्पेस है वह सुरक्षित रहे।

until

until कंस्ट्रक्ट कमांड के क्रम को तब तक दोहराता है जब तक कोई शर्त गलत रहती है। लूप जब तक शर्त सही नहीं हो जाती, तब तक दोहराता है।

until CONDITION_COMMANDS; do COMMANDS; done

until का उपयोग शायद ही किया जाता है। इसके बजाय "while not" लूप का उपयोग ज़्यादा आम है।

while ! CONDITION_COMANDS; do ...

अनंत लूप

कभी-कभी आप हमेशा के लिए लूप चलाना चाहते हैं। इसे करने के दो तरीके हैं।

  1. ऐसा while लूप जिसकी शर्त का एग्ज़िट स्टेटस हमेशा सफल रहता है

    while true; do ...
    
  2. खाली एक्सप्रेशन वाला अंकगणितीय for लूप

    for ((;;)); do ...
    

डू-वाइल

डू-वाइल के लिए कोई अलग कंस्ट्रक्ट नहीं है, लेकिन आप इसी असर को ऐसे पा सकते हैं:

while true; do
    COMMANDS

    if END_CONDITION; then
        break
    fi
done
GitHub के ज़रिए संपादित करें यह लिंक नई विंडो या टैब में खुलता है।