Nekonečná slučka while v skripte BASH. BASH: popis slučiek for, while, till a príklady použitia Príklad: vyhľadávanie spustiteľných súborov


Autor: Paul Cobbaut
Dátum zverejnenia: 16.10.2014
Preklad: A. Panin
Dátum prekladu: 21. december 2014

Kapitola 22. Slučky v skriptoch

testovací príkaz

Príkaz test vám umožňuje určiť, či je výraz pravdivý alebo nepravdivý. Začnime testovaním, či je celočíselná hodnota 10 väčšia ako celočíselná hodnota 55. $ test 10 -gt 55 ; echo $? 1 dolár

Ak je výraz nepravdivý, príkaz test vráti 1. A ako uvidíte v nasledujúcom príklade, príkaz test vráti 0, ak sa výraz vyhodnotí ako true. $ test 56 -gt 55 ; echo $? 0 USD

Ak vám viac vyhovuje práca s reťazcami true a false, môžete použiť príkaz test, ako je uvedené nižšie. $ test 56 -gt 55 && echo true || echo false true $ test 6 -gt 55 && echo true || ozvena nepravda nepravda

Príkaz test možno nahradiť aj hranatými zátvorkami, takže príkazy v príklade nižšie sú úplne rovnaké ako príkazy v príklade vyššie. $ [ 56 -gt 55 ] && echo true || echo false true $ [ 6 -gt 55 ] && echo true || ozvena nepravda nepravda

Nižšie sú uvedené príklady implementácií niektorých kontrol. Prehľad nájdete na stránke mužského testu pridané vlastnosti vykonávanie rôznych kontrol. [ -d foo ] Existuje adresár foo? [ -e bar ] Existuje súbor bar? [ "/etc" = $PWD ] Je /etc ekvivalentné hodnote $PWD? [ $1 != "secret" ] Líši sa hodnota prvého parametra skriptu od tajného reťazca? [ 55 -lt $bar ] Je celočíselná hodnota 55 menšia ako hodnota $bar? [ $foo -ge 1000 ] Je hodnota $foo väčšia alebo rovná celočíselnej hodnote 1000? ["abc"< $bar ] Будет ли строка abc расположена выше значения переменной $bar в списке после сортировки? [ -f foo ] Является ли foo обычным файлом? [ -r bar ] Является ли bar čitateľný súbor? [ foo -nt bar ] Je foo novší ako bar ? [ -o nounset ] Je povolená voľba shell nounset?

Kontrolné operátory možno kombinovať s operátormi zodpovedajúcimi logické operácie„A“ a „ALEBO“. paul@RHEL4b:~$ [ 66 -gt 55 -a 66 -lt 500 ] && echo true || echo false true paul@RHEL4b:~$ [ 66 -gt 55 -a 660 -lt 500 ] && echo true || echo false false paul@RHEL4b:~$ [ 66 -gt 55 -o 660 -lt 500 ] && echo true || echo nepravda pravda

Podmienený skok ak potom inak

Konštrukt if then else je určený na výber možnosti kódu. Ak je určitá podmienka pravdivá, vykoná sa nejaký kód, inak sa vykoná nejaký iný kód. Nižšie uvedený príklad kontroluje existenciu súboru, po ktorom, ak sa potvrdí predpoklad existencie súboru, sa zobrazí zodpovedajúca správa. #!/bin/bash, ak [ -f isit.txt ], potom echo súbor isit.txt existuje! else echo súbor isit.txt nenájdený! fi

V prípade, že ušetríme tento kód skript v súbore s názvom "choice", možno ho spustiť rovnakým spôsobom. $ ./choice súbor isit.txt sa nenašiel! $ touch isit.txt $ ./výber súbor isit.txt existuje! $

Podmienený skok ak potom elif

Môžete uverejniť príspevok nového operátora podmienený skok, ak je vnútri bloku else pomocou operátora elif. Nižšie je uvedený jednoduchý príklad takéhoto záznamu. #!/bin/bash count=42 if [ $count -eq 42 ] potom echo "42 je platná hodnota." elif [ $count -gt 42 ] potom echo "Too many." inak echo "Nestačí." fi

pre slučku

Nižšie uvedený príklad ukazuje syntax klasickej slučky for v bash shell. lebo ja v 1 2 4 do echo $i hotovo

Príklad použitia cyklu for v kombinácii s inline volaním shellu. #!/bin/ksh pre počítadlo v `seq 1 20` robiť echo počítanie od 1 do 20, aktuálna hodnota $counter sleep 1 done

Skript úplne podobný tomu, ktorý je uvedený vyššie, je možné vytvoriť bez použitia vstavaného príkazového shellu pomocou deklarácie bash shell pre rozsah hodnôt (od value..to value). #!/bin/bash for counter in (1..20) do echo counting od 1 do 20, momental value $counter sleep 1 done

Táto slučka for používa mechanizmus na vyhľadávanie súborov podľa vzoru (implementovaný ako súčasť mechanizmu rozšírenia príkazov). Ak sú vyššie uvedené pokyny uverejnené priamo v príkazový riadok, bude fungovať podobne. kahlan@soleexp11$ ls count.ksh go.ksh kahlan@soleexp11$ pre súbor v *.ksh ; do cp $subor $subor.zaloha ; hotovo kahlan@soleexp11$ ls count.ksh count.ksh.backup go.ksh go.ksh.backup

pričom slučka

Nižšie je uvedený jednoduchý príklad použitia cyklu while. i=100; pričom [ $i -ge 0 ] ; do echo Odpočítavanie od 100 do 0, aktuálna hodnota $i; nech som--; hotový

Nekonečné cykly je možné implementovať pomocou deklarácií while true alebo while:, kde symbol: je ekvivalentom chýbajúcej operácie v Korn shell a bash. #!/bin/ksh # nekonečná slučka while: do echo hello sleep 1 done

Až do slučky

Nižšie je uvedený jednoduchý príklad použitia cyklu do. nech i=100; do [ $i -le 0 ] ; do echo Odpočítavanie od 100 do 1, aktuálna hodnota $i; nech som--; hotový

Cvičenie: Testy a slučky v skriptoch

3. Vytvorte skript, ktorý bude používať cyklus while na počítanie od 3 do 7.

4. Vytvorte skript, ktorý bude používať cyklus do na odpočítavanie od 8 do 4.

5. Vytvorte skript, ktorý bude počítať súbory s príponou .txt v aktuálnom adresári.

6. Použite príkaz if vo vytvorenom skripte, aby fungoval správne, ak sa v aktuálnom adresári nenachádzajú žiadne súbory s príponou .txt.

Správny postup plnenia praktickej úlohy: kontroly a slučky v skriptoch

1. Vytvorte skript, ktorý bude používať cyklus for na počítanie od 3 do 7.

#!/bin/bash for i in 3 4 5 6 7 do echo Počítanie od 3 do 7, aktuálna hodnota $i hotovo

2. Vytvorte skript, ktorý bude používať cyklus for na počítanie od 1 do 17 000.

Shell bash podporuje cykly, ktoré vám umožňujú iterovať sekvencie hodnôt. Tak to je základná štruktúra takéto cykly:

Pre var v zozname urob príkaz hotový
V každej iterácii cyklu sa premenná var zapíše na nasledujúcu hodnotu zoznam. Prvý prechod cyklu teda použije prvú hodnotu zo zoznamu. V druhej - druhej a tak ďalej - kým slučka nedosiahne posledný prvok.

Iterácia cez jednoduché hodnoty

Snáď najjednoduchším príkladom cyklu for v bash skriptoch je iterácia cez zoznam jednoduchých hodnôt:

#!/bin/bash pre var v prvej druhej tretine štvrtej piatej do echo Položka $var hotovo
Výsledky tohto skriptu sú uvedené nižšie. Jasne vidíte, že premenná $var obsahuje prvky zo zoznamu postupne. To sa deje, kým cyklus nedosiahne posledný z nich.


Jednoduché pre slučku

Upozorňujeme, že premenná $var si pri výstupe z cyklu zachováva svoju hodnotu, jej obsah je možné meniť a vo všeobecnosti s ňou môžete pracovať ako s ktoroukoľvek inou premennou.

Iterácia cez zložité hodnoty

Zoznam použitý na inicializáciu cyklu for môže obsahovať nielen jednoduché reťazce pozostávajúce z jedného slova, ale aj celé frázy, ktoré obsahujú niekoľko slov a interpunkčných znamienok. Môže to vyzerať napríklad takto:

#!/bin/bash pre var v prvej "druhej" "tretej" "Urobím to" urobiť echo "Toto je: $var" hotovo
Toto sa stane, keď táto slučka prejde zoznamom. Ako vidíte, výsledok je celkom očakávaný.


Iterácia cez zložité hodnoty
TNW-CUS-FMP – propagačný kód na zľavu 10 % na naše služby, k dispozícii na aktiváciu do 7 dní“

Inicializácia slučky so zoznamom získaným z výsledkov príkazu

Ďalším spôsobom, ako inicializovať cyklus for, je odovzdať mu zoznam, ktorý je výsledkom príkazu. Tu sa na ich vykonanie a získanie výsledkov ich práce používa nahradenie príkazov.

#!/bin/bash file="myfile" pre var v $(cat $file) urobiť echo " $var" hotovo
Tento príklad používa príkaz cat, ktorý číta obsah súboru. Výsledný zoznam hodnôt sa odovzdá do slučky a zobrazí sa na obrazovke. Upozorňujeme, že súbor, ku ktorému pristupujeme, obsahuje zoznam slov oddelených riadkami, nepoužívajú sa žiadne medzery.


Slučka, ktorá prechádza cez obsah súboru

Tu musíme počítať s tým, že takýto prístup, ak sa predpokladá spracovanie dát po riadkoch, nebude fungovať pre súbor zložitejšej štruktúry, ktorého riadky môžu obsahovať niekoľko slov oddelených medzerami. Slučka spracuje jednotlivé slová, nie riadky.

Čo ak to vôbec nie je to, čo potrebujete?

Separátory polí

Dôvodom vyššie uvedenej funkcie je špeciálnosť premenná prostredia, ktorý sa nazýva IFS (Internal Field Separator) a umožňuje určiť oddeľovače polí. V predvolenom nastavení bash shell považuje nasledujúce znaky za oddeľovače polí:
  • Priestor
  • Znak tabulátora
  • Riadkový znak
Ak bash narazí na niektorý z týchto znakov v údajoch, predpokladá sa, že mu predchádza nasledujúca nezávislá hodnota v zozname.

Ak chcete problém vyriešiť, môžete dočasne zmeniť premennú prostredia IFS. Tu je návod, ako to urobiť v bash skripte, za predpokladu, že ako oddeľovač polí potrebujete iba nový riadok:

IFS=$"\n"
Keď tento príkaz pridáte do svojho bash skriptu, bude fungovať podľa očakávania, pričom bude ignorovať medzery a tabulátory a ako oddeľovače polí bude zaobchádzať iba so znakmi nového riadku.

#!/bin/bash file="/etc/passwd" IFS=$"\n" pre var v $(cat $file) urobiť echo " $var" hotovo
Ak je tento skript spustený, vypíše presne to, čo sa od neho vyžaduje, pričom v každej iterácii cyklu poskytne prístup k ďalšiemu riadku zapísanému do súboru.


Prechádzanie súboru po riadkoch v slučke for

Oddeľovačmi môžu byť aj iné znaky. Napríklad vyššie sme zobrazili obsah súboru /etc/passwd. Užívateľské údaje v riadkoch sú oddelené dvojbodkami. Ak potrebujete spracovať takéto reťazce v slučke, IFS možno nakonfigurovať takto:

Prechádzanie súbormi obsiahnutými v adresári

Jedným z najbežnejších použití slučiek for v bash skriptoch je prechádzať súbormi umiestnenými v adresári a spracovávať tieto súbory.

Tu je napríklad postup, ako zobraziť zoznam súborov a priečinkov:

#!/bin/bash pre súbor v /home/likegeeks/* urobte if [ -d "$file" ] potom echo "$file je adresár" elif [ -f "$file" ] potom echo "$file je súbor" je hotový
Ak ste porozumeli predchádzajúcemu materiálu v tejto sérii článkov, mali by ste pochopiť štruktúru konštruktu if-then, ako aj to, ako rozlíšiť súbor od priečinka. Ak je pre vás ťažké porozumieť vyššie uvedenému kódu, prečítajte si tento materiál znova.

Toto je výstup skriptu.


Zobrazenie obsahu priečinka

Venujte pozornosť tomu, ako inicializujeme slučku, a to divoká karta"*" na konci adresy priečinka. Tento symbol si možno predstaviť ako zástupný znak, ktorý znamená: „všetky súbory s ľubovoľnými názvami“. umožňuje organizovať automatická substitúcia názvy súborov, ktoré zodpovedajú vzoru.

Pri testovaní podmienky v príkaze if uzatvárame názov premennej do úvodzoviek. Je to spôsobené tým, že názov súboru alebo priečinka môže obsahovať medzery.

C-štýl pre slučky

Ak poznáte programovací jazyk C, syntax na opis slučiek bash for sa vám môže zdať divná, pretože ste očividne zvyknutí opisovať slučky týmto spôsobom:

Pre (i = 0; i< 10; i++) { printf("number is %d\n", i); }
V bash skriptoch môžete použiť pre slučky, ktorých popis vyzerá veľmi podobne ako slučky v štýle C, aj keď existujú určité rozdiely. Cyklický diagram s týmto prístupom vyzerá takto:

For ((počiatočná hodnota premennej; podmienka pre ukončenie cyklu; zmena premennej))
V bash to môže byť napísané takto:

Pre ((a = 1; a< 10; a++))
Tu je pracovný príklad:

#!/bin/bash pre ((i=1; i<= 10; i++)) do echo "number is $i" done
Tento kód zobrazí zoznam čísel od 1 do 10.

Slučka v štýle C

pričom slučka

Konštrukt for nie je jediný spôsob, ako organizovať slučky v bash skriptoch. Tu môžete použiť aj slučky while. V takejto slučke môžete zadať príkaz na kontrolu určitej podmienky a vykonať telo cyklu, kým testovaná podmienka nevráti nulu alebo signál pre úspešné dokončenie určitej operácie. Keď podmienka cyklu vráti nenulovú hodnotu, čo znamená chybu, cyklus sa zastaví.

Tu je schéma organizácie slučiek while
zatiaľ čo príkaz na kontrolu stavu
robiť
ostatné tímy
hotový

Pozrime sa na príklad skriptu s takýmto cyklom:

#!/bin/bash var1=5 while [ $var1 -gt 0 ] do echo $var1 var1=$[ $var1 - 1 ] hotovo
Na vstupe do cyklu sa kontroluje, či je premenná $var1 väčšia ako nula. Ak áno, vykoná sa telo cyklu, v ktorom sa jedna odpočíta od hodnoty premennej. Deje sa tak v každej iterácii a pred úpravou vytlačíme hodnotu premennej do konzoly. Akonáhle $var1 dosiahne hodnotu 0, cyklus sa zastaví.

Výsledok cyklu while

Ak neupravíte premennú $var1, skript sa ocitne v nekonečnej slučke.

Vnorené slučky

Môžete použiť ľubovoľné príkazy v tele cyklu, vrátane spúšťania iných cyklov. Takéto konštrukcie sa nazývajú vnorené slučky:

#!/bin/bash pre ((a = 1; a<= 3; a++)) do echo "Start $a:" for ((b = 1; b <= 3; b++)) do echo " Inner loop: $b" done done
Nižšie je uvedený výstup tohto skriptu. Ako vidíte, najskôr sa vykoná prvá iterácia vonkajšej slučky, potom tri iterácie vnútornej, po jej skončení prichádza do hry opäť vonkajšia slučka, potom opäť vnútorná.

Vnorené slučky

Spracovanie obsahu súboru

Najčastejšie sa na spracovanie súborov používajú vnorené slučky. Vonkajšia slučka teda iteruje cez riadky súboru a vnútorná už pracuje s každým riadkom. Tu je napríklad, ako vyzerá spracovanie súboru /etc/passwd:

#!/bin/bash IFS=$"\n" pre položku v $(cat /etc/passwd) urobte echo "Hodnoty v $entry –" IFS=: pre hodnotu v $entry urobte echo " $value" hotovo hotový
V tomto skripte sú dve slučky. Prvý prechádza cez riadky pomocou znaku nového riadku ako oddeľovača. Interná je zaneprázdnená analýzou reťazcov, ktorých polia sú oddelené dvojbodkami.

Spracovanie údajov súboru

Tento prístup je možné použiť pri spracovaní súborov CSV alebo akýchkoľvek podobných súborov tak, že podľa potreby zapíšete znak oddeľovača do premennej prostredia IFS.

Riadenie cyklu

Možno ho po vstupe do cyklu budete musieť zastaviť, keď premenná cyklu dosiahne určitú hodnotu, ktorá nezodpovedá pôvodne zadanej podmienke ukončenia cyklu. Bude v takejto situácii potrebné čakať na normálne dokončenie cyklu? Samozrejme, že nie a v takýchto prípadoch prídu vhod nasledujúce dva príkazy:
  • prestávka
  • ďalej

príkaz prerušiť

Tento príkaz vám umožňuje prerušiť vykonávanie cyklu. Môže byť použitý pre slučky for a while:

#!/bin/bash pre var1 v 1 2 3 4 5 6 7 8 9 10 urobte if [ $var1 -eq 5 ] potom zlomte fi echo "Číslo: $var1" hotovo
Takáto slučka za normálnych podmienok prejde celým zoznamom hodnôt zo zoznamu. V našom prípade sa však jeho vykonávanie preruší, keď sa premenná $var1 rovná 5.

Predčasné ukončenie cyklu for

Tu je to isté, ale pre cyklus while:

#!/bin/bash var1=1 while [ $var1 -lt 10 ] urob if [ $var1 -eq 5 ] then break fi echo "Iterácia: $var1" var1=$(($var1 + 1)) hotovo
Príkaz break, ktorý sa vykoná, keď $var1 dosiahne 5, preruší cyklus. Konzola zobrazí to isté ako v predchádzajúcom príklade.

pokračovať v príkaze

Keď sa s týmto príkazom stretnete v tele cyklu, aktuálna iterácia sa skončí skôr a začne sa ďalšia bez toho, aby sa cyklus opustil. Pozrime sa na príkaz continue v slučke for:

#!/bin/bash pre ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
Keď je splnená podmienka vnútri cyklu, to znamená, keď $var1 je väčší ako 5 a menší ako 10, shell vykoná príkaz continue. Výsledkom je preskočenie zostávajúcich príkazov v tele cyklu a prechod na ďalšiu iteráciu.

Príkaz continue v slučke for

Výstup spracovania beží v slučke

Dátový výstup zo slučky možno spracovať buď presmerovaním výstupu, alebo jeho odovzdaním do potrubia. To sa dosiahne pridaním príkazov na spracovanie výstupu za príkaz done.

Napríklad namiesto zobrazovania výstupov v slučke na obrazovke môžete všetko zapísať do súboru alebo odovzdať niekde inde:

#!/bin/bash pre ((a = 1; a< 10; a++)) do echo "Number is $a" done >myfile.txt echo "dokončené."
Shell vytvorí súbor myfile.txt a presmeruje výstup príkazu for do tohto súboru. Otvorme súbor a uistite sa, že obsahuje presne to, čo očakávame.

Presmerujte výstup slučky do súboru

Príklad: Vyhľadajte spustiteľné súbory

Využime to, čo sme už prebrali a napíšme niečo užitočné. Ak napríklad potrebujete zistiť, ktoré spustiteľné súbory sú v systéme k dispozícii, môžete skenovať všetky priečinky zaznamenané v premennej prostredia PATH. Už máme celý arzenál nástrojov, ktoré na to potrebujeme, len to musíme dať dokopy:

#!/bin/bash IFS=: pre priečinok v $PATH urobiť echo "$folder:" pre súbor v $folder/* urobiť if [ -x $file ] potom echo " $file" fi hotovo
Tento malý a jednoduchý skript nám umožnil získať zoznam spustiteľných súborov uložených v priečinkoch z PATH.

Vyhľadávanie spustiteľných súborov v priečinkoch z premennej PATH

Výsledky

Dnes sme hovorili o slučkách for a while v bash skriptoch, ako ich spúšťať a ako ich spravovať. Teraz viete, ako spracovať reťazce s rôznymi oddeľovačmi v slučkách, viete, ako presmerovať výstup údajov v slučkách do súborov, ako prezerať a analyzovať obsah adresárov.

Ak predpokladáme, že ste vývojár bash skriptov, ktorý o nich vie len to, čo je uvedené v prvej časti tejto série článkov a v tejto druhej, tak už môžete napísať niečo užitočné. Pred nami je tretia časť, po pochopení ktorej sa naučíte, ako odovzdávať parametre a prepínače príkazového riadku do bash skriptov a čo s tým všetkým robiť.

Stručný popis rozdielu v typoch slučiek:

for - vykoná akciu, pokiaľ existujú objekty na vykonanie (napríklad čítanie streamu z stdin, súboru alebo funkcie);
kým - vykoná akciu do stave je pravda;
do - sa bude vykonávať dovtedy, kým stave sa nestane pravdou, t.j. zatiaľ je to falošné.

PRE slučku

Zoberme si túto verziu skriptu so slučkou:

$ cat loop.sh #!/bin/bash pre premennú v `ls -1` do echo "$variable" hotovo

Syntax je veľmi jednoduchá a je celkom jasne znázornená v príklade:

for (spustenie cyklu) premenná (deklarácia premennej, s ktorou budeme vykonávať akcie) v (odoslanie toku do cyklu) `ls -1` (príkaz, ktorý sa má vykonať a odovzdať do premennej $variable). Do a done sú „telo“ slučky, v rámci ktorého sa vykonajú hlavné akcie s prijatými údajmi a echo „$variable“ je skutočná akcia vykonaná slučkou.

Teraz trochu zmeníme príklad a namiesto explicitného zadania príkazu použijeme druhú premennú:

$ cat loop.sh #!/bin/bash ls=`ls -1` pre premennú v $ls do echo "$variable" hotovo

Teraz je príkaz ls -1 odovzdaný v samostatnej premennej, čo umožňuje flexibilnejšie pracovať so slučkou. Namiesto premennej v slučke môžete použiť aj funkciu:

$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) pre premennú v `lsl` urobiť echo "$variable" hotovo

Hlavnou podmienkou cyklu for je, že sa vykoná, pokiaľ príkaz, ktorý mu bol odovzdaný, obsahuje objekty na akciu. Na základe vyššie uvedeného príkladu - pokiaľ má ls -1 súbory na zobrazenie - cyklus ich odovzdá premennej a vykoná "telo slučky". Hneď ako zoznam súborov v adresári skončí, cyklus dokončí svoje vykonávanie.

Urobme príklad trochu zložitejším.

Adresár obsahuje zoznam súborov:

$ ls -1 súbor1 súbor2 súbor3 súbor4 súbor5 loop.sh nofile1 nofile2 nofile3 nofile4 nofile5

Musíme z nich vybrať len tie, ktoré nemajú slovo „ č«:

$ cat loop.sh #!/bin/bash lsl=`ls -1` pre premennú v $lsl do echo "$variable" | grep -v "nie" hotovo $ ./loop.sh súbor1 súbor2 súbor3 súbor4 súbor5 loop.sh

Môžete tiež použiť podmienené výrazy v slučke ( podmienené výrazy) […] na kontrolu podmienok a príkaz break na prerušenie cyklu, ak sa podmienka spustí.

Zvážte tento príklad:

$ cat loop.sh #!/bin/bash lsl=`ls -1` pre premennú v $lsl urob, ak [ $premenná != "loop.sh" ] potom echo "$premenná" | grep -v "nie" else break fi hotovo

Cyklus bude pokračovať, kým nenájdete súbor loop.sh. Hneď ako vykonanie cyklu dosiahne tento súbor, cyklus sa preruší príkazom break:

$ ./loop.sh súbor1 súbor2 súbor3 súbor4 súbor5

Ďalším príkladom je použitie aritmetických operácií bezprostredne pred vykonaním tela cyklu:

$ cat loop.sh #!/bin/bash for ((počet=1; počet<11; count++)) do echo "$count" done

Tu nastavíme tri riadiace príkazy – počet=1, riadiacu podmienku – pričom počet je menší ako 11 a príkaz na vykonanie – počet +1:

slučky WHILE a UNTIL

Jednoduchý príklad, ktorý jasne ukazuje, ako funguje cyklus while:

$ cat loop.sh #!/bin/bash count=0 while [ $count -lt 10 ] do ((count++)) echo $count done

Premennú $count nastavíme na nulu a potom spustíme cyklus whi le s podmienkou „keď je $count menší ako desať, vykonajte cyklus“. V tele cyklu vykonáme postfixový prírastok+1 k premennej $count a výsledok sa vytlačí na stdout.

Výsledok vykonania:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10

Akonáhle sa hodnota premennej $count stala 10, cyklus sa zastavil.

Dobrý príklad „nekonečnej“ slučky, ktorá ukazuje, ako funguje while:

$ cat loop.sh #!/bin/bash count=10 while [ 1 = 1 ] do ((count++)) echo $count done $ ./loop.sh ... 5378 5379 5380 5381 5382 5383 ^C

Slučka do funguje podobne, ale v opačnom smere:

$ cat loop.sh #!/bin/bash count=0 do [ $count -gt 10 ] do ((count++)) echo $count done

Tu nastavíme podobnú podmienku, ale namiesto „kým je premenná menšia ako 10“, zadáme „kým sa premenná nestane väčšou ako 10“. Výsledok vykonania:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10 11

Ak sa vyššie uvedený príklad „nekonečnej slučky“ vykoná pomocou príkazu do, nevypíše nič, na rozdiel od while:

$ cat loop.sh #!/bin/bash count=10 do [ 1 = 1 ] do ((count++)) echo $count done $ ./loop.sh $

pretože" stave"pôvodne" pravda"— telo cyklu sa nevykoná.

Rovnako ako v slučke for môžete používať funkcie počas a do. Napríklad slučka zo skutočného skriptu, ktorá kontroluje stav servera kocúr(PID sa preberá zo systému SLES, môže sa líšiť v iných systémoch), mierne zjednodušená verzia:

$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) pričom check_tomcat_status vykonajte if [ -n "$ RUN" ] potom printf "UPOZORNENIE: Tomcat stále beží s PID $RUN." else printf "Tomcat zastavený, pokračuje...nn" break fi hotovo

Výsledok vykonania:

$ ./loop.sh UPOZORNENIE: Tomcat stále beží s PID 14435 26548. UPOZORNENIE: Tomcat stále beží s PID 14435 26548. UPOZORNENIE: Tomcat stále beží s PID 14435 26548.UPOZORNENIE: Tomcat stále beží s PID5RNcat 265443 beží s PID 14435 26548. UPOZORNENIE: Tomcat stále beží s PID 14435 26548. VAROVANIE: Tomcat stále beží s PID 14435 26548. VAROVANIE: Tomcat stále beží s PID 14435

Plná verzia:

Check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(tlač $2)"`) while check_tomcat_status; urob if [ -n "$RUN" ] potom printf "UPOZORNENIE: Tomcat stále beží s PID $RUN. Zastaviť ho?" odpovedzte "Zastavuje sa Tomcat..." "Prebieha inštalácia..." && $CATALINA_HOME/bin/shutdown sh 2&>1 /dev/null || break sleep 2 if [ -n "$RUN" ] then printf "Tomcat stále beží. Zabiť ho?" odpoveď "Killing Tomcat..." "Prebieha inštalácia...n" && zabiť $RUN || prerušiť spánok 2 fi else printf "Tomcat zastavený, pokračuje...nn" break fi hotovo

Funkcia odpovede bola opísaná v článku, ale tu je použitá mierne vylepšená verzia:

Odpoveď () (pri čítaní odpovede; do echo case $response in |) printf "$1n" return 0 break ;; |) printf "$2n" vráti 1 prerušenie ;; *) printf "Prosím, zadajte Y(áno) alebo N(nie)!" esac hotovo )

Tu bolo možné použiť while aj till - ale nie cyklus for, pretože for by raz fungoval (prijal PID a skončil).

Slučky sú mimoriadne pohodlná vec pri písaní akýchkoľvek programov alebo skriptov, ba dokonca nevyhnutná. Umožňujú nám vykonať určitú časť kódu stanovený počet krát. Prirodzene, bash má niekoľko typov slučiek. Popíšeme cykly for in, for, while, before. Hoci for in a for sa považujú za rôzne syntaxe toho istého výroku, podľa môjho názoru sa navzájom líšia viac ako while od do.

Slučka s počítadlom pre in:

Cyklus pre in Toto je slučka s počítadlom. Blok kódu umiestnený v tele cyklu sa opakuje toľkokrát, koľko je hodnôt obsiahnutých v zozname operátora for in a pri každom opakovaní sa premenná počítadla (tu sa nazýva var, ale samozrejme môžete to nazvať ako chcete) má hodnotu ďalšieho prvku zoznamu.
Ak je kľúčové slovo do na rovnakom riadku ako slovo pre, potom za zoznam argumentov (pred do) musíte vložiť bodkočiarku.
Každý z prvkov<список>môže obsahovať viacero argumentov. To je užitočné pri spracovaní skupín parametrov. V tomto prípade vynútiť analýzu každého z argumentov v<списке>, musíte použiť nastavený návod
Premennú môžete použiť ako zoznam v slučke for.
IN<списке>Cyklus for môže používať názvy súborov, ktoré zase môžu obsahovať zástupné znaky. To môže byť veľmi užitočné pri práci s veľkým počtom súborov.
Ak<список>nie je špecifikovaný v cykle for, potom sa ako to použije premenná $@ - zoznam argumentov príkazového riadku.
Pri vytváraní zoznamu argumentov môžete použiť náhradu príkazov v slučke for.
Výstup cyklu môže byť presmerovaný z stdout do súboru alebo niekde inde (viac sa o tom dozviete pri pohľade na I/O presmerovanie).

Syntax:
pre var v<список>
robiť
<выполняемые команды>
hotový

Príklad:
pre mená v meno1 meno2 meno3 meno4
robiť
echo $names
hotový

Operátor slučky pre má iný spôsob zápisu - veľmi podobný syntaxi operátora for v jazyku C. V tomto prípade sa pri inicializácii počítadiel nastavia počiatočné hodnoty premenných alebo jednej premennej a po každom prechode cyklu sa podmienka je skontrolovaný, ak kontrola vráti hodnotu true, potom začne ďalší prechod cyklu. V bloku<приращение счётчиков>hodnota našich premenných počítadiel sa musí nevyhnutne meniť (nie nevyhnutne smerom nahor), aby pri kontrole podmienky skôr či neskôr dostala hodnotu false, inak sa cyklus nikdy neskončí. Veľmi pohodlná a hlavne známa možnosť, ak je potrebné akúkoľvek operáciu opakovať stanovený počet krát.

S podobnou syntaxou:
pre ((<инициализация счётчиков>; <проверка условия>; <приращение счётчиков>))
robiť
<выполняемые команды>
hotový

Príklad:
pre ((var=1; var<= LIMIT ; var++))
robiť
echo $var
hotový

while cyklus:

Ide o pomerne jednoduchú konštrukciu, ktorá kontroluje stav za operátorom zatiaľ čo a ak je táto podmienka pravdivá, vykoná blok príkazov umiestnených medzi slovami do a done a potom znova prejde na kontrolu podmienky. Ak kontrola vráti hodnotu false, cyklus sa skončí a začnú sa vykonávať nasledujúce príkazy: hotový. Je nevyhnutné to zabezpečiť<проверка условия>záviselo od kódu spusteného v slučke; inak, ak sa výsledok kontroly nezmení, dostanete nekonečnú slučku.
Štandardné vstupné zariadenie pre slučku while môže byť presmerované do súboru pomocou príkazu presmerovanie< в конце цикла.

Syntax:
zatiaľ čo<Проверка условия>
robiť
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
hotový

Príklad:
zatiaľ čo [ $var0 -eq 100]
robiť
echo $var
var++
hotový

Operátor zatiaľ čo môže mať viacero podmienok. Ale len posledný z nich určuje možnosť pokračovania cyklu. V tomto prípade sa syntax operátora slučky bude líšiť od bežnej.
Syntax(Ešte raz opakujem, že iba posledná podmienka ovplyvňuje vykonanie cyklu) :
zatiaľ čo
<условие1>
<условие2>

<условиеN>
robiť
<выполняемые команды - тело цикла>
hotový

Do slučky:

Operátor kým je veľmi podobný while, tiež vyhodnotí podmienku, ale vykoná telo cyklu, ak je výsledok výpočtu nepravdivý. Môže sa to zdať nezvyčajné, ale kým nevyhodnotí podmienku pred prvým prechodom cyklu, napríklad while, a nie po ňom. Rovnako ako pri cykloch for/in, pri umiestnení kľúčového slova do na rovnaký riadok ako deklarácia cyklu musíte vložiť znak ";". pred robiť.
Rovnako ako v predchádzajúcom prípade je dôležité pamätať na to, že podmienka musí závisieť od operácií v tele cyklu, inak sa náš skript nikdy nedokončí.

Syntax:
kým<Проверка условия>
robiť
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
hotový

Príklad:
do [ $var0 -gt 100] # Podmienka sa skontroluje na začiatku iterácie.
robiť
echo $var
var--
hotový

Zatiaľ to asi stačí. :)

  • späť
  • Vpred

Nové články:

  • Zisťovanie siete sa nezapne v systéme Windows 7/8/2008/2012
  • Chyba: Túto aplikáciu sa nepodarilo spustiť, pretože nemohla nájsť alebo načítať doplnok „windows“ platformy Qt.
  • Konfigurácia automatického reštartu pracovných procesov rphost.exe na serveri 1C 8.3
  • Ako zmenšiť veľkosť protokolu transakcií (.ldf) v MS SQL 2008/20012

    MS SQL, ako každý slušný priemyselný DBMS, spolu s databázou uchováva protokoly transakcií, ktoré vám umožňujú vrátiť stav...

0 Meeran Bala-Kumaran

Naozaj sa snažím pochopiť, prečo táto slučka while nikdy nekončí, keď sa slučka spustí, moja premenná LOC je nastavená na Testing/ čo je adresár, ktorý som vytvoril na testovanie tohto programu, má nasledujúce rozloženie:

Chcem, aby sa cyklus skončil, keď všetky adresáre použijú funkciu „count“.
Tu je to, čo som skúšal;

Skontroloval som funkciu počítania a nevytvára nekonečnú slučku

Pokúsil som sa spustiť algoritmus manuálne

PARSE=1 LOC=$LOC/ count AVAILABLEDIR=$(ls $LOC -AFl | sed "1 d" | grep "/$" | awk "( print $9 )"), kým [ $PARSE = "1" ] urobí, ak [[ $(DOSTUPNÉ[@]) == "" ]]; potom PARSE=0 fi DIRBASE=$LOC pre a v $(DOSTUPNÉ IR[@]); do LOC="$(DIRBASE)$(a)" LOCLIST="$LOCLIST $LOC" počet vykonaný pre a v $(LOCLIST[@]); do TMPAVAILABLEDIR=$(ls $a -AFl | sed "1 d" | grep "/$" | awk "( vytlačiť $9 )") PREPEND=$a if [[ $(TMPAVAILABLEDIR[@]) == "" ] ]; potom pokračujte fi pre a v $(TMPAVAILABLEDIR[@]); do TMPAVAILABLEDIR2="$TMPAVAILABLEDIR2 $(PREPEND[@])$(a)" hotovo NEWAVAILABLEDIR="$NEWAVAILABLEDIR $TMPAVAILABLEDIR2" hotovo AVAILABLEDIR=$NEWAVAILABLEDIR NEWAVAILABLEDIR="" LOC="" hotovo

Naozaj bojujem a každý príspevok by som veľmi ocenil, snažil som sa na to prísť posledné dve hodiny.

bash nekonečná slučka

4 odpovede

Mali by ste skúsiť spustiť skript s argumentom -x alebo ho napísať na prvý riadok:

#!/bin/bash -x

Potom vám povie všetko, čo robí.

V tomto prípade si môžete všimnúť dve chyby:

    TMPAVAILABLEDIR2 nikdy nenačítate znova

    Môžete tiež robiť ls na bežných súboroch.

Ak sa naozaj musíte vyhnúť rekurzii, skúste toto úplne bez rekurzie:

#!/bin/bash count() ( echo counting "$1" ) todo=(Testing) while test $(#todo[@]) != 0 do doit=("$(todo[@])") todo= () pre dir v "$(doit[@])" urobte pre položku "$dir"/* # ak je dir prázdny, zobrazí sa záznam s názvom "*" do test -e "$entry" || pokračovať # preskočiť záznam "*" prázdneho dir testu "$entry" -d "$entry" || pokračovať todo+=("$entry") hotovo hotovo hotovo

Povedzte mi však, prečo nemôžete použiť rekurziu? Je to nejaký druh alergie? Sľub? Existujú nejaké miestne zákony proti rekurzívnemu softvéru v mieste, kde žijete?

Napísali ste, že chcete vykonať "spočet" všetkých rezov. Pozrite si možnosti vyhľadávania:

Nájdite $LOC -typ d | pri čítaní dir; do cd $LOC cd $(dir) count hotový

alebo kratšie (keď vaše počítadlo funkcií berie adresár ako parameter 1)

Nájdite $LOC -typ d | počet xargov

Teraz vidím, že nechcete použiť find alebo ls -R (rekurzívna funkcia). Potom by ste si mali vytvoriť vlastnú rekurzívnu funkciu ako

Funkcia parseDir ( ls -d */ $1 | pri čítaní adresára; dopočítať parseDir $1/$dir hotovo )

Netuším, či to bude fungovať, ale je to zaujímavá otázka, na ktorú som nemohol prestať myslieť. Veľa štastia

Aj keď je to pravda; urobte pre slovo v "$(echo *)" ; urobiť if [[ -d "$word" ]] ; potom d[$((i++))]="$PWD"/"$word" elif [[ -f "$word" ]] ;potom f[$((j++))]="$PWD"/"$ slovo" fi hotovo [[ $k -gt $i ]] && cd .. cd "$d[$((k++))]" || prestávka hotová