Beskonačna while petlja u BASH skripti. BASH: opis za, while, do petlje i primjeri upotrebe Primjer: traženje izvršnih datoteka


Autor: Paul Cobbaut
Datum objave: 16. oktobar 2014
Prijevod: A. Panin
Datum prevoda: 21. decembar 2014

Poglavlje 22. Petlje u skriptama

test komanda

Test komanda vam omogućava da odredite da li je izraz tačan ili netačan. Počnimo testiranjem da li je vrijednost cijelog broja 10 veća od vrijednosti cijelog broja 55. $ test 10 -gt 55 ; echo $? 1$

Test komanda vraća 1 ako je izraz lažan. I, kao što ćete vidjeti u sljedećem primjeru, test naredba će vratiti 0 ako izraz procijeni na istinito. $ test 56 -gt 55 ; echo $? $0

Ako vam je ugodnije raditi sa stringovima true i false, možete koristiti test naredbu kao što je prikazano u nastavku. $ test 56 -gt 55 && echo true || echo false true $ test 6 -gt 55 && echo true || echo false false

Test naredba se također može zamijeniti uglastim zagradama, tako da su naredbe u primjeru ispod potpuno iste kao naredbe u gornjem primjeru. $ [ 56 -gt 55 ] && echo true || echo false true $ [ 6 -gt 55 ] && echo true || echo false false

Ispod su primjeri implementacije nekih provjera. Pogledajte stranicu za testiranje man za pregled dodatne funkcije sprovođenje raznih provjera. [ -d foo ] Da li direktorijum foo postoji? [ -e bar ] Da li bar datoteka postoji? [ "/etc" = $PWD ] Da li je /etc ekvivalentno vrijednosti $PWD? [ $1 != "tajna" ] Da li se vrijednost prvog parametra skripte razlikuje od tajnog niza? [ 55 -lt $bar ] Je li cjelobrojna vrijednost 55 manja od vrijednosti $bara? [ $foo -ge 1000 ] Je li vrijednost $foo veća ili jednaka cjelobrojnoj vrijednosti 1000? ["abc"< $bar ] Будет ли строка abc расположена выше значения переменной $bar в списке после сортировки? [ -f foo ] Является ли foo обычным файлом? [ -r bar ] Является ли bar čitljiv fajl? [ foo -nt bar ] Je li foo noviji od bara? [ -o nounset ] Da li je omogućena opcija ljuske skupa imenica?

Operatori provjere mogu se kombinirati s operatorima koji odgovaraju logičke operacije"AND" i "OR". 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 false true

Uslovni skok ako onda drugačije

Konstrukcija if then else namijenjena je odabiru opcije koda. Ako je određeni uslov ispunjen, neki kod će se izvršiti, u suprotnom će se izvršiti neki drugi kod. Primjer ispod provjerava postojanje datoteke, nakon čega se, ako se potvrdi pretpostavka o postojanju datoteke, prikazuje odgovarajuća poruka. #!/bin/bash ako [ -f isit.txt ] onda ponovite da datoteka isit.txt postoji! inače echo fajl isit.txt nije pronađen! fi

U slučaju da uštedimo ovaj kod skriptu u datoteci pod nazivom "choice", može se izvršiti na isti način. $ ./choice fajl isit.txt nije pronađen! $ touch isit.txt $ ./choice fajl isit.txt postoji! $

Uslovni skok ako onda elif

Možete objavljivati novi operater uslovni skok ako je unutar drugog bloka koristeći elif operator. Ispod je jednostavan primjer takvog unosa. #!/bin/bash count=42 ako [ $count -eq 42 ] onda echo "42 je važeća vrijednost." elif [ $count -gt 42 ] zatim echo "Previše." else echo "Nije dovoljno." fi

za petlju

Primjer ispod pokazuje sintaksu klasične for petlje u bash shell-u. for i in 1 2 4 do echo $i done

Primjer korištenja for petlje u kombinaciji s inline pozivom ljuske. #!/bin/ksh za brojač u `seq 1 20` uradi eho brojeći od 1 do 20, trenutna vrijednost $counter sleep 1 završeno

Skripta potpuno slična onoj gore predstavljenoj može se kreirati bez upotrebe ugrađene komandne ljuske korištenjem deklaracije bash shell-a za raspon vrijednosti (od vrijednosti.. do vrijednosti). #!/bin/bash za brojač u (1..20) uradi eho brojanje od 1 do 20, trenutna vrijednost $counter sleep 1 završeno

Ova for petlja koristi mehanizam za pretraživanje datoteka po obrascu (primijenjen kao dio mehanizma za proširenje naredbi). Ako su gornja uputstva postavljena direktno u komandna linija, funkcionirat će slično. kahlan@solexp11$ ls count.ksh go.ksh kahlan@solexp11$ za datoteku u *.ksh ; uradite cp $file $file.backup ; done kahlan@solexp11$ ls count.ksh count.ksh.backup go.ksh go.ksh.backup

while petlja

Ispod je jednostavan primjer korištenja while petlje. i=100; dok [ $i -ge 0 ] ; do echo Odbrojavanje od 100 do 0, trenutna vrijednost $i; neka i--; urađeno

Beskonačne petlje se mogu implementirati koristeći while true ili while: deklaracije, gdje je simbol: ekvivalent operacije koja nedostaje u Korn ljusci i bash-u. #!/bin/ksh # beskonačna petlja while: do echo hello sleep 1 gotovo

Do petlje

Ispod je jednostavan primjer korištenja do petlje. neka i=100; dok [ $i -le 0 ] ; do echo Odbrojavanje od 100 do 1, trenutna vrijednost $i; neka i--; urađeno

Vježba: Testovi i petlje u skriptama

3. Razvijte skriptu koja će koristiti while petlju za brojanje od 3 do 7.

4. Razvijte skriptu koja će koristiti petlju do za odbrojavanje od 8 do 4.

5. Razvijte skriptu koja će brojati datoteke sa ekstenzijom .txt u trenutnom direktoriju.

6. Koristite if naredbu u kreiranoj skripti da bi ona ispravno radila ako u trenutnom direktoriju nema datoteka sa ekstenzijom .txt.

Ispravan postupak za ispunjavanje praktičnog zadatka: provjere i petlje u skriptama

1. Razvijte skriptu koja će koristiti for petlju za brojanje od 3 do 7.

#!/bin/bash za i u 3 4 5 6 7 do echo Brojanje od 3 do 7, trenutna vrijednost $i urađeno

2. Razvijte skriptu koja će koristiti for petlju za brojanje od 1 do 17000.

Bash shell podržava for petlje, koje vam omogućavaju ponavljanje niza vrijednosti. To je ono što je osnovna struktura takvi ciklusi:

Za var in listu do naredba je urađena
U svakoj iteraciji petlje, varijabla var će biti upisana u sljedeću vrijednost iz lista. Prvi prolaz petlje će stoga koristiti prvu vrijednost sa liste. U drugom - drugom, i tako dalje - dok petlja ne dođe do posljednjeg elementa.

Iteracija preko jednostavnih vrijednosti

Možda najjednostavniji primjer for petlje u bash skriptama je ponavljanje preko liste jednostavnih vrijednosti:

#!/bin/bash za var u prvoj drugoj trećoj četvrtoj petoj do echo $var stavka je gotova
Rezultati ove skripte su prikazani u nastavku. Možete jasno vidjeti da varijabla $var sadrži elemente sa liste sekvencijalno. To se dešava sve dok ciklus ne dođe do posljednjeg od njih.


Jednostavna for petlja

Imajte na umu da varijabla $var zadržava svoju vrijednost pri izlasku iz petlje, njen sadržaj se može mijenjati i općenito, s njom možete raditi kao sa bilo kojom drugom varijablom.

Iteracija preko kompleksnih vrijednosti

Lista koja se koristi za inicijalizaciju for petlje može sadržavati ne samo jednostavne nizove koji se sastoje od jedne riječi, već i cijele fraze koje sadrže nekoliko riječi i znakova interpunkcije. Na primjer, to može izgledati ovako:

#!/bin/bash za var u prvom "drugom" "trećem" "Ja ću to učiniti" do echo "Ovo je: $var" gotovo
Ovo se dešava nakon što ova petlja prođe kroz listu. Kao što vidite, rezultat je sasvim očekivan.


Iteracija preko kompleksnih vrijednosti
TNW-CUS-FMP - promo kod za 10% popusta na naše usluge, dostupan za aktivaciju u roku od 7 dana"

Inicijalizacija petlje sa listom dobijenom iz rezultata naredbe

Drugi način da se inicijalizira for petlja je da joj proslijedite listu, koja je rezultat naredbe. Ovdje se zamjena komandi koristi za njihovo izvršavanje i dobijanje rezultata njihovog rada.

#!/bin/bash file="myfile" za var u $(cat $file) do echo " $var" gotovo
Ovaj primjer koristi naredbu cat, koja čita sadržaj datoteke. Rezultirajuća lista vrijednosti se prosljeđuje u petlju i prikazuje na ekranu. Imajte na umu da datoteka kojoj pristupamo sadrži listu riječi odvojenih novim redovima; ne koriste se razmaci.


Petlja koja prolazi kroz sadržaj datoteke

Ovdje moramo uzeti u obzir da takav pristup, ako se očekuje obrada podataka red po red, neće raditi za datoteku složenije strukture, čiji redovi mogu sadržavati nekoliko riječi odvojenih razmacima. Petlja će obraditi pojedinačne riječi, a ne linije.

Šta ako ovo uopšte nije ono što vam treba?

Separatori polja

Razlog za gornju karakteristiku je posebnost varijabla okruženja, koji se zove IFS (Internal Field Separator) i omogućava vam da odredite separatore polja. Podrazumevano, bash shell smatra sljedeće znakove kao separatore polja:
  • Prostor
  • Tab znak
  • Line feed znak
Ako bash naiđe na bilo koji od ovih znakova u podacima, pretpostavlja da mu prethodi sljedeća nezavisna vrijednost na listi.

Da biste riješili problem, možete privremeno promijeniti varijablu okruženja IFS. Evo kako to učiniti u bash skripti, pod pretpostavkom da vam je potreban samo novi red kao separator polja:

IFS=$"\n"
Jednom kada dodate ovu naredbu svojoj bash skripti, ona će raditi kako se očekuje, ignorirajući razmake i tabulatore i tretirajući samo znakove novog reda kao separatore polja.

#!/bin/bash file="/etc/passwd" IFS=$"\n" za var u $(cat $file) do echo " $var" gotovo
Ako se ova skripta pokrene, ona će ispisati tačno ono što se od nje traži, dajući, u svakoj iteraciji petlje, pristup sljedećem redu upisanom u datoteku.


Red po red prelazak datoteke u for petlji

Razdjelnici mogu biti i drugi znakovi. Na primjer, iznad smo prikazali sadržaj datoteke /etc/passwd. Korisnički podaci u redovima su odvojeni dvotočkama. Ako trebate obraditi takve nizove u petlji, IFS se može konfigurirati ovako:

Prelazak datoteka sadržanih u direktoriju

Jedna od najčešćih upotreba for petlji u bash skriptama je prolazak kroz datoteke koje se nalaze u direktoriju i obradu tih datoteka.

Na primjer, evo kako navesti datoteke i foldere:

#!/bin/bash za datoteku u /home/likegeeks/* uradi ako [ -d "$file" ] zatim echo "$file je direktorij" elif [ -f "$file" ] zatim echo "$file je fajl" fi urađeno
Ako ste razumjeli prethodni materijal u ovoj seriji članaka, trebali biste razumjeti strukturu if-then konstrukcije, kao i kako razlikovati datoteku od mape. Ako vam je teško razumjeti gornji kod, ponovo pročitajte ovaj materijal.

Ovo je ono što će skripta ispisati.


Prikaz sadržaja fascikle

Obratite pažnju na to kako inicijalizujemo petlju, naime divlja karta"*" na kraju adrese foldera. Ovaj simbol se može smatrati zamjenskim znakom koji znači: “sve datoteke s bilo kojim imenima”. omogućava vam da se organizujete automatska zamena imena datoteka koji odgovaraju uzorku.

Kada testiramo uslov u if naredbi, stavljamo ime varijable u navodnike. Ovo se radi zato što naziv datoteke ili fascikle može sadržavati razmake.

C-stil za petlje

Ako ste upoznati s programskim jezikom C, sintaksa za opisivanje bash for petlji može vam se učiniti čudnom, jer ste očito navikli opisivanje petlji na ovaj način:

Za (i = 0; i< 10; i++) { printf("number is %d\n", i); }
U bash skriptama možete koristiti for petlje, čiji opis izgleda vrlo slično petljama u C stilu, iako postoje neke razlike. Dijagram ciklusa s ovim pristupom izgleda ovako:

Za ((početna vrijednost varijable; uvjet za završetak petlje; promjena varijable))
U bash-u se može napisati ovako:

Za ((a = 1; a< 10; a++))
Evo radnog primjera:

#!/bin/bash za ((i=1; i<= 10; i++)) do echo "number is $i" done
Ovaj kod će prikazati listu brojeva od 1 do 10.

Petlja u C stilu

while petlja

For konstrukcija nije jedini način da se organiziraju petlje u bash skriptama. Ovdje također možete koristiti while petlje. U takvoj petlji možete odrediti naredbu za provjeru određenog stanja i izvršavanje tijela petlje sve dok uvjet koji se testira ne vrati nulu, ili signal za uspješan završetak određene operacije. Kada uslov petlje vrati vrijednost različitu od nule, što znači grešku, petlja će se zaustaviti.

Evo dijagrama organizacije while petlji
dok naredba za provjeru stanja
uradi
drugim timovima
urađeno

Pogledajmo primjer skripte sa petljom poput ove:

#!/bin/bash var1=5 dok [ $var1 -gt 0 ] echo $var1 var1=$[ $var1 - 1 ] gotovo
Na ulazu u petlju provjerava se da li je varijabla $var1 veća od nule. Ako je tako, izvršava se tijelo petlje, u kojem se jedan oduzima od vrijednosti varijable. Ovo se dešava u svakoj iteraciji, a mi ispisujemo vrijednost varijable na konzolu prije nego što se modificira. Čim $var1 dostigne vrijednost 0, petlja se zaustavlja.

Rezultat while petlje

Ako ne modificirate varijablu $var1, to će uzrokovati da skripta završi u beskonačnoj petlji.

Ugniježđene petlje

Možete koristiti bilo koje komande u tijelu petlje, uključujući pokretanje drugih petlji. Takve konstrukcije se nazivaju ugniježđene petlje:

#!/bin/bash za ((a = 1; a<= 3; a++)) do echo "Start $a:" for ((b = 1; b <= 3; b++)) do echo " Inner loop: $b" done done
Ispod je šta će ova skripta ispisati. Kao što vidite, prvo se izvršava prva iteracija vanjske petlje, zatim tri iteracije unutrašnje, nakon njenog završetka ponovo dolazi u igru ​​vanjska petlja, zatim opet unutrašnja.

Ugniježđene petlje

Obrada sadržaja datoteke

Najčešće se ugniježđene petlje koriste za obradu datoteka. Dakle, vanjska petlja se ponavlja preko linija datoteke, a unutrašnja već radi sa svakom linijom. Evo, na primjer, kako izgleda obrada /etc/passwd datoteke:

#!/bin/bash IFS=$"\n" za unos u $(cat /etc/passwd) do echo "Vrijednosti u $entry –" IFS=: za vrijednost u $entry ponoviti " $value" urađeno urađeno
U ovoj skripti postoje dvije petlje. Prvi prelazi redove koristeći znak novog reda kao graničnik. Interni je zauzet raščlanjivanjem stringova čija su polja odvojena dvotočkama.

Obrada podataka datoteke

Ovaj pristup se može koristiti prilikom obrade CSV datoteka, ili bilo koje slične datoteke, upisivanjem znaka za razdvajanje u varijablu okruženja IFS po potrebi.

Upravljanje ciklusom

Možda ćete nakon ulaska u petlju morati da je zaustavite kada varijabla petlje dostigne određenu vrijednost koja ne odgovara inicijalno specificiranom uvjetu za završetak petlje. Da li će u takvoj situaciji biti potrebno čekati normalan završetak ciklusa? Naravno da ne, iu takvim slučajevima će vam dobro doći sljedeće dvije naredbe:
  • break
  • nastaviti

break command

Ova komanda vam omogućava da prekinete izvođenje petlje. Može se koristiti i za for i while petlje:

#!/bin/bash za var1 u 1 2 3 4 5 6 7 8 9 10 uradi ako [ $var1 -eq 5 ] zatim break fi echo "Broj: $var1" urađeno
Takva petlja, u normalnim uslovima, proći će kroz cijelu listu vrijednosti sa liste. Međutim, u našem slučaju, njegovo izvršenje će biti prekinuto kada je varijabla $var1 jednaka 5.

Rani izlazak iz for petlje

Evo iste stvari, ali za while petlju:

#!/bin/bash var1=1 dok [ $var1 -lt 10 ] radi ako [ $var1 -eq 5 ] zatim prekida fi echo "Iteracija: $var1" var1=$(($var1 + 1)) gotovo
Komanda break, koja se izvršava kada $var1 dostigne 5, prekida petlju. Konzola će prikazati istu stvar kao u prethodnom primjeru.

nastavi komandu

Kada se ova naredba nađe u tijelu petlje, trenutna iteracija se završava ranije i počinje sljedeća, bez izlaska iz petlje. Pogledajmo naredbu nastavak u for petlji:

#!/bin/bash za ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
Kada je uslov unutar petlje zadovoljen, to jest, kada je $var1 veći od 5 i manji od 10, ljuska izvršava naredbu za nastavak. Ovo rezultira preskakanjem preostalih naredbi u tijelu petlje i prelaskom na sljedeću iteraciju.

Naredba nastavljanja u for petlji

Obrada izlaza se izvodi u petlji

Izlaz podataka iz petlje može se obraditi bilo preusmjeravanjem izlaza ili prosljeđivanjem u cjevovod. Ovo se radi dodavanjem naredbi za obradu izlaza nakon naredbe done.

Na primjer, umjesto da na ekranu prikazujete ono što se izlazi u petlji, možete sve to zapisati u datoteku ili proslijediti negdje drugdje:

#!/bin/bash za ((a = 1; a< 10; a++)) do echo "Number is $a" done >myfile.txt echo "završeno."
Shell će kreirati datoteku myfile.txt i preusmjeriti izlaz for naredbe u tu datoteku. Otvorimo datoteku i uvjerimo se da sadrži upravo ono što očekujemo.

Preusmjerite izlaz petlje u datoteku

Primjer: Potražite izvršne datoteke

Iskoristimo ono što smo već pokrili i napišimo nešto korisno. Na primjer, ako trebate saznati koje su izvršne datoteke dostupne na sistemu, možete skenirati sve mape snimljene u varijablu okruženja PATH. Već imamo cijeli arsenal alata koji su nam potrebni za ovo, samo trebamo sve to spojiti:

#!/bin/bash IFS=: za folder u $PATH ponoviti "$folder:" za datoteku u $folder/* uraditi ako [ -x $file ] zatim ponoviti " $file" fi gotovo
Ova skripta, mala i jednostavna, omogućila nam je da dobijemo listu izvršnih datoteka pohranjenih u folderima iz PATH.

Traženje izvršnih datoteka u folderima iz PATH varijable

Rezultati

Danas smo pričali o for i while petljama u bash skriptama, kako ih pokrenuti i kako njima upravljati. Sada znate kako obraditi nizove sa različitim graničnicima u petljama, znate kako preusmjeriti izlaz podataka u petljama na datoteke, kako pregledati i analizirati sadržaj direktorija.

Ako pretpostavimo da ste programer bash skripti koji o njima zna samo ono što je navedeno u prvom dijelu ove serije članaka, a u ovom drugom, onda već možete napisati nešto korisno. Pred vama je treći dio, nakon razumijevanja kojeg ćete naučiti kako proslijediti parametre i prekidače komandne linije bash skriptama, te šta sa svime raditi.

Kratak opis razlike u tipovima petlji:

for - će izvršiti akciju sve dok postoje objekti za izvršenje (na primjer, čitanje toka iz stdin-a, datoteke ili funkcije);
dok - izvršava radnju do stanje istina je;
do - će se izvršavati sve dok stanje neće postati istina, tj. za sada je lažno.

FOR Loop

Razmotrimo ovu verziju skripte sa petljom:

$ cat loop.sh #!/bin/bash za varijablu u `ls -1` do echo "$varijable" urađeno

Sintaksa je vrlo jednostavna i prilično je jasno prikazana u primjeru:

for (pokreni petlju) varijabla (deklariraj varijablu na kojoj ćemo izvoditi radnje) u (pošalji tok u petlju) `ls -1` (naredba koja se izvršava i prosljeđuje varijablu $varijable). Do i done su “tijelo” petlje, unutar kojeg će se glavne radnje izvršiti na primljenim podacima, a echo “$varijable” je stvarna akcija koju petlja izvodi.

Sada ćemo malo promijeniti primjer i umjesto eksplicitnog navođenja naredbe, koristit ćemo drugu varijablu:

$ cat loop.sh #!/bin/bash ls=`ls -1` za varijablu u $ls do echo "$varijable" urađeno

Sada se naredba ls -1 prosljeđuje u zasebnoj varijabli, što vam omogućava fleksibilniji rad s petljom. Umjesto varijable u petlji, možete koristiti i funkciju:

$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) za varijablu u `lsl` do echo "$varijable" urađeno

Glavni uslov for petlje je da će biti izvršena sve dok komanda koja joj je prosleđena sadrži objekte za akciju. Na osnovu gornjeg primjera - sve dok ls -1 ima datoteke za prikaz - petlja će ih proslijediti promjenljivoj i izvršiti "tijelo petlje". Čim se završi lista datoteka u direktoriju, petlja će završiti svoje izvršavanje.

Učinimo primjer malo kompliciranijim.

Direktorij sadrži listu datoteka:

$ ls -1 file1 file2 file3 file4 file5 loop.sh nofile1 nofile2 nofile3 nofile4 nofile5

Od njih trebamo odabrati samo one koji nemaju riječ " br«:

$ cat loop.sh #!/bin/bash lsl=`ls -1` za varijablu u $lsl do echo "$varijable" | grep -v "ne" urađeno $ ./loop.sh file1 file2 file3 file4 file5 loop.sh

Također možete koristiti uslovne izraze u petlji ( uslovni izrazi) […] za provjeru uvjeta i naredbu break za prekid petlje ako se uvjet pokrene.

Razmotrite ovaj primjer:

$ cat loop.sh #!/bin/bash lsl=`ls -1` za varijablu u $lsl uradi if [ $variable != "loop.sh" ] onda echo "$varijable" | grep -v "ne" inače prekid fi urađeno

Petlja će se nastaviti sve dok se ne naiđe na datoteku loop.sh. Čim izvršenje petlje dođe do ovog fajla, petlja će biti prekinuta naredbom break:

$ ./loop.sh file1 file2 file3 file4 file5

Drugi primjer je korištenje aritmetičkih operacija neposredno prije izvršavanja tijela petlje:

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

Ovdje postavljamo tri kontrolne komande - count=1, kontrolni uslov - dok je count manji od 11 i naredbu za izvršenje - count +1:

WHILE i UNTIL petlje

Jednostavan primjer koji jasno pokazuje kako funkcionira while petlja:

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

Postavljamo varijablu $count na nulu, a zatim pokrećemo while petlju sa uslovom "dok je $count manji od deset, izvrši petlju." U tijelu petlje izvršavamo postfiks inkrement+1 na varijablu $count i rezultat se ispisuje na stdout.

Rezultat izvršenja:

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

Čim je vrijednost varijable $count postala 10, petlja je prestala.

Dobar primjer "beskonačne" petlje koja pokazuje kako while funkcionira:

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

Petlja do radi slično, ali u suprotnom smjeru:

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

Ovdje postavljamo sličan uslov, ali umjesto „dok je varijabla manja od 10“, navodimo „dok varijabla ne postane veća od 10“. Rezultat izvršenja:

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

Ako se gornji primjer "beskonačne petlje" izvrši pomoću do, neće ništa ispisati, za razliku od while:

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

jer " stanje"izvorno" istinito"—tijelo petlje neće biti izvršeno.

Baš kao u for petlji, možete koristiti funkcije u while i do. Na primjer, petlja iz skripte iz stvarnog života koja provjerava status servera Tomcat(PID se preuzima iz sistema SLES, može se razlikovati u drugim sistemima), malo pojednostavljena verzija:

$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) dok check_tomcat_status radi ako [ -n "$ RUN" ] zatim printf "UPOZORENJE: Tomcat i dalje radi sa PID $RUN." else printf "Tomcat zaustavljen, nastavlja...nn" prekid fi urađen

Rezultat izvršenja:

$ ./loop.sh UPOZORENJE: Tomcat i dalje radi sa PID 14435 26548.UPOZORENJE: Tomcat i dalje radi sa PID 14435 26548.UPOZORENJE: Tomcat i dalje radi sa PID 14435 26548.UPOZORENJE: Tomcat i dalje radi sa PID 14435 26548. UPOZORENJE: Tomcat i dalje radi sa PID435 TomWARN56. radi sa PID 14435 26548.UPOZORENJE: Tomcat i dalje radi sa PID 14435 26548.UPOZORENJE: Tomcat i dalje radi sa PID 14435 26548.UPOZORENJE: Tomcat i dalje radi sa PID 14435

Puna verzija:

Check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) dok check_tomcat_status; uradi ako [ -n "$RUN" ] onda printf "UPOZORENJE: Tomcat još uvijek radi sa PID $RUN. Zaustavi ga? " odgovori "Zaustavljanje Tomcat..." "Nastavak instalacije..." && $CATALINA_HOME/bin/shutdown sh 2&>1 /dev/null || break sleep 2 if [ -n "$RUN" ] then printf "Tomcat i dalje radi. Ubiti ga?" odgovorite "Ubijanje Tomcata..." "Nastavak instalacije...n" && kill $RUN || break sleep 2 fi else printf "Tomcat zaustavljen, nastavlja...nn" break fi je urađen

Funkcija odgovora je opisana u članku, ali ovdje se koristi malo poboljšana verzija:

Odgovor () (dok je odgovor čitanja; echo case $response u |) printf "$1n" return 0 break ;; |) printf "$2n" vraća 1 prekid ;; *) printf "Molimo, unesite Y(da) ili N(ne)! " esac done )

Ovdje je bilo moguće koristiti i while i do - ali ne i for petlju, jer bi for jednom radio (primio PID i završio).

Petlje su izuzetno zgodna stvar kada se piše bilo koji program ili skripta, čak i neophodna. Oni nam omogućavaju da izvršimo određeni dio koda određeni broj puta. Naravno, bash ima nekoliko tipova petlji. Opisaćemo cikluse za, za, dok, dok. Iako se za in i za smatraju različitim sintaksama iste izjave, po mom mišljenju one se međusobno više razlikuju nego while od do.

Petlja sa brojačem za in:

Ciklus za in Ovo je petlja sa brojačem. Blok koda koji se nalazi u telu petlje ponavlja se onoliko puta koliko ima vrednosti sadržanih u listi for in operatora, a sa svakim ponavljanjem promenljiva brojača (ovde se zove var, ali naravno možete ga nazvati kako god želite) ima vrijednost sljedećeg elementa liste.
Ako je ključna riječ do u istom redu kao i riječ for, onda nakon liste argumenata (prije do) morate staviti tačku i zarez.
Svaki od elemenata<список>može sadržavati više argumenata. Ovo je korisno kada se obrađuju grupe parametara. U ovom slučaju, za prisilno raščlanjivanje svakog od argumenata u<списке>, morate koristiti set instrukciju
Možete koristiti varijablu kao listu u for petlji.
IN<списке>Petlja for može koristiti nazive datoteka, koji zauzvrat mogu sadržavati zamjenske znakove. Ovo može biti vrlo korisno kada radite s velikim brojem datoteka.
Ako<список>nije specificirano u for petlji, tada se varijabla $@ koristi kao ona - lista argumenata komandne linije.
Kada kreirate listu argumenata, možete koristiti zamjenu naredbi u for petlji.
Izlaz petlje se može preusmjeriti iz standardnog izlaza u datoteku ili negdje drugdje (možete saznati više o tome gledajući I/O preusmjeravanje).

sintaksa:
za var in<список>
uradi
<выполняемые команды>
urađeno

primjer:
za imena u ime1 ime2 ime3 ime4
uradi
echo $names
urađeno

Operator petlje za ima drugi način pisanja - vrlo sličan sintaksi operatora for u jeziku C. U ovom slučaju, prilikom inicijalizacije brojača, postavljaju se početne vrijednosti varijabli ili jedne varijable i nakon svakog prolaska petlje ispunjava se uvjet je označeno, ako provjera vrati true, tada počinje sljedeći prolaz petlje. U bloku<приращение счётчиков>vrijednost naših brojača varijable mora se nužno promijeniti (ne nužno naviše) tako da prilikom provjere uvjeta prije ili kasnije dobijemo vrijednost false, inače se petlja nikada neće završiti. Vrlo zgodna i što je najvažnije poznata opcija ako bilo koju operaciju treba ponoviti određeni broj puta.

Sa sličnom sintaksom:
za ((<инициализация счётчиков>; <проверка условия>; <приращение счётчиков>))
uradi
<выполняемые команды>
urađeno

primjer:
za ((var=1; var<= LIMIT ; var++))
uradi
echo $var
urađeno

while petlja:

Ovo je prilično jednostavna konstrukcija koja provjerava stanje iza operatera dok i ako je ovaj uslov tačan, on izvršava blok naredbi koji se nalazi između riječi do i done, a zatim ponovo prelazi na provjeru uvjeta. Ako provjera vrati false, ciklus se završava i sljedeće naredbe počinju da se izvršavaju: urađeno. To je neophodno osigurati<проверка условия>zavisi od koda koji se izvodi u petlji; u suprotnom, ako se rezultat provjere ne promijeni, dobit ćete beskonačnu petlju.
Standardni ulazni uređaj za while petlju može se preusmjeriti na datoteku pomoću naredbe za preusmjeravanje< в конце цикла.

sintaksa:
dok<Проверка условия>
uradi
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
urađeno

primjer:
dok [ $var0 -eq 100 ]
uradi
echo $var
var++
urađeno

Operater dok može imati nekoliko uslova. Ali samo posljednji od njih određuje mogućnost nastavka ciklusa. U ovom slučaju, sintaksa operatora petlje će se razlikovati od uobičajene.
Sintaksa(Još jednom ponavljam da samo zadnji uslov utiče na izvršenje petlje) :
dok
<условие1>
<условие2>

<условиеN>
uradi
<выполняемые команды - тело цикла>
urađeno

Do petlje:

Operater do je vrlo sličan while, također procjenjuje uvjet, ali izvršava tijelo petlje ako je rezultat izračunavanja lažan. Možda izgleda neobično, ali do procjenjuje stanje prije prvog prolaza petlje, kao while, a ne nakon njega. Kao i kod for/in petlje, kada stavite ključnu riječ do u isti red kao i deklaracija petlje, morate umetnuti znak ";". prije nego uradi.
Kao iu prethodnom slučaju, važno je zapamtiti da uslov mora zavisiti od operacija u telu petlje, inače naša skripta nikada neće završiti.

sintaksa:
do<Проверка условия>
uradi
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
urađeno

primjer:
do [ $var0 -gt 100] # Uslov se provjerava na početku iteracije.
uradi
echo $var
var--
urađeno

To je vjerovatno dovoljno za sada. :)

  • Nazad
  • Naprijed

Novi članci:

  • Otkrivanje mreže se ne uključuje u Windows 7/8/2008/2012
  • Greška: Ova aplikacija nije uspjela da se pokrene jer nije mogla pronaći ili učitati dodatak Qt platforme "windows".
  • Konfiguriranje automatskog ponovnog pokretanja radnih procesa rphost.exe na 1C 8.3 serveru
  • Kako smanjiti veličinu dnevnika transakcija (.ldf) u MS SQL 2008/20012

    MS SQL, kao i svaki pristojan industrijski DBMS, zajedno sa bazom podataka, čuva dnevnike transakcija koji vam omogućavaju da vratite stanje...

0 Meeran Bala-Kumaran

Stvarno pokušavam razumjeti zašto se ova while petlja nikada ne završava, kada petlja započne moja LOC varijabla je postavljena na Testing/, što je direktorij koji sam kreirao da testiram ovaj program ima sljedeći izgled:

Želim da se petlja završi kada svi direktoriji imaju primijenjenu funkciju "count".
Evo šta sam pokušao;

Provjerio sam funkciju brojanja i ona ne stvara beskonačnu petlju

Pokušao sam ručno pokrenuti algoritam

PARSE=1 LOC=$LOC/ count AVAILABLEDIR=$(ls $LOC -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") dok [ $PARSE = "1" ] radi ako [[ $(AVAILABLEDIR[@]) == "" ]]; onda PARSE=0 fi DIRBASE=$LOC za a u $(AVAILABLEDIR[@]); do LOC="$(DIRBASE)$(a)" LOCLIST="$LOCLIST $LOC" broj obavljen za a u $(LOCLIST[@]); do TMPAVAILABLEDIR=$(ls $a -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") PREPEND=$a ako [[ $(TMPAVAILABLEDIR[@]) == "" ] ]; zatim nastavi fi za a u $(TMPAVAILABLEDIR[@]); do TMPAVAILABLEDIR2="$TMPAVAILABLEDIR2 $(PREPEND[@])$(a)" urađeno NEWAVAILABLEDIR="$NEWAVAILABLEDIR $TMPAVAILABLEDIR2" urađeno AVAILABLEDIR=$NEWAVAILABLEDIR NEWAVAILABLEDIR="" LOC="" urađeno

Zaista se mučim i svaki doprinos bi bio veoma zahvalan, pokušavam ovo da shvatim poslednja dva sata.

bash beskonačna petlja

4 odgovora

Trebali biste pokušati pokrenuti skriptu s argumentom -x ili je napisati u prvom redu:

#!/bin/bash -x

Onda vam kaže sve što radi.

U ovom slučaju možete primijetiti dvije greške:

    Nikada ne učitavate ponovo TMPAVAILABLEDIR2

    Takođe radite ls na redovnim fajlovima.

Ako zaista morate izbjeći rekurziju, pokušajte ovo, potpuno bez rekurzije:

#!/bin/bash count() ( eho broji "$1" ) todo=(Testiranje) dok test $(#todo[@]) != 0 do doit=("$(todo[@])") todo= () za dir u "$(doit[@])" uradi za unos u "$dir"/* # ako je dir prazan, ovo pokazuje unos pod nazivom "*" do test -e "$entry" || nastavi # preskoči unos "*" praznog broja dir "$entry" test -d "$entry" || nastavi todo+=("$entry") gotovo urađeno urađeno

Međutim, molim vas recite mi zašto ne možete koristiti rekurziju? Je li ovo neka vrsta alergije? Zavjet? Postoje li lokalni zakoni protiv rekurzivnog softvera tamo gdje živite?

Napisali ste da želite da izvršite "prebrojavanje" na svim rezovima. Provjerite opcije pretraživanja:

Pronađite $LOC -tip d | dok čitate dir; do cd $LOC cd $(dir) count done

ili kraće (kada vaš brojač funkcije uzima imenik kao parametar 1)

Pronađite $LOC -tip d | xargs count

Sada vidim da ne želite da koristite find ili ls -R (rekurzivna funkcija). Tada biste trebali napraviti svoju vlastitu rekurzivnu funkciju kao

Funkcija parseDir ( ls -d */ $1 | dok čita dir; računaj parseDir $1/$dir urađeno)

Nemam pojma hoće li ovo uspjeti, ali to je zanimljivo pitanje o kojem nisam mogao prestati razmišljati. Sretno

Dok je istina ; uradi za riječ u "$(echo *)" ; uradi ako [[ -d "$word" ]] ; zatim d[$((i++))]="$PWD"/"$word" elif [[ -f "$word" ]] ;zatim f[$((j++))]="$PWD"/"$ word" fi done [[ $k -gt $i ]] && cd .. cd "$d[$((k++))]" || break done