Neskončna zanka while v skriptu BASH. BASH: opis zank for, while, until in primeri uporabe Primer: iskanje izvedljivih datotek


Avtor: Paul Cobbaut
Datum objave: 16. oktober 2014
Prevod: A. Panin
Datum prevoda: 21. december 2014

Poglavje 22. Zanke v skriptih

preizkusni ukaz

Ukaz test vam omogoča, da ugotovite, ali je izraz resničen ali napačen. Začnimo s testiranjem, ali je vrednost celega števila 10 večja od vrednosti celega števila 55. $ test 10 -gt 55 ; echo $? 1 $

Testni ukaz vrne 1, če je izraz napačen. In kot boste videli v naslednjem primeru, bo testni ukaz vrnil 0, če je izraz ovrednoten kot true. $ test 56 -gt 55 ; echo $? 0 $

Če vam je bolj udobno delati z nizoma true in false, lahko uporabite testni ukaz, kot je prikazano spodaj. $ test 56 -gt 55 && echo true || echo false true $ test 6 -gt 55 && echo true || echo false false

Testni ukaz lahko zamenjate tudi z oglatimi oklepaji, tako da so ukazi v spodnjem primeru popolnoma enaki ukazom v zgornjem primeru. $ [ 56 -gt 55 ] && echo true || echo false true $ [ 6 -gt 55 ] && echo true || echo false false

Spodaj so primeri implementacij nekaterih pregledov. Za pregled si oglejte testno stran človeka dodatne lastnosti izvajanje različnih pregledov. [ -d foo ] Ali imenik foo obstaja? [ -e bar ] Ali datoteka bar obstaja? [ "/etc" = $PWD ] Ali je /etc enakovreden vrednosti $PWD? [ $1 != "secret" ] Ali se vrednost prvega parametra skripta razlikuje od skrivnega niza? [ 55 -lt $bar ] Ali je cela vrednost 55 manjša od vrednosti $bar ? [ $foo -ge 1000 ] Ali je vrednost $foo večja ali enaka celoštevilski vrednosti 1000? ["abc"< $bar ] Будет ли строка abc расположена выше значения переменной $bar в списке после сортировки? [ -f foo ] Является ли foo обычным файлом? [ -r bar ] Является ли bar berljiva datoteka? [foo -nt bar] Je foo novejši od bara? [ -o nounset ] Ali je možnost lupine nounset omogočena?

Operatorje preverjanja je mogoče kombinirati z operatorji, ki ustrezajo logične operacije"IN" in "ALI". 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

Pogojni skok če potem drugače

Konstrukcija if then else je namenjena izbiri možnosti kode. Če je določen pogoj resničen, bo izvedena neka koda, v nasprotnem primeru bo izvedena druga koda. Spodnji primer preveri obstoj datoteke, nato pa se, če je domneva o obstoju datoteke potrjena, prikaže ustrezno sporočilo. #!/bin/bash if [ -f isit.txt ] then echo datoteka isit.txt obstaja! sicer echo datoteke isit.txt ni mogoče najti! fi

V primeru, da prihranimo to kodo skript v datoteki z imenom "choice", ga je mogoče izvesti na enak način. $ ./izbirna datoteka isit.txt ni najdena! $ dotaknite se isit.txt $ ./izbirna datoteka isit.txt obstaja! $

Pogojni skok if then elif

Lahko objavite nov operater pogojni skok, če je znotraj bloka else z uporabo operaterja elif. Spodaj je preprost primer takega vnosa. #!/bin/bash count=42 if [ $count -eq 42 ] then echo "42 je veljavna vrednost." elif [ $count -gt 42 ] nato echo "Preveč." else echo "Ni dovolj." fi

za zanko

Spodnji primer prikazuje sintakso klasične zanke for v lupini bash. for i in 1 2 4 do echo $i done

Primer uporabe zanke for v kombinaciji s klicem lupine v vrstici. #!/bin/ksh za števec v `seq 1 20` do echo štetja od 1 do 20, trenutna vrednost $counter spanje 1 done

Skript, ki je popolnoma podoben zgoraj predstavljenemu, je mogoče ustvariti brez uporabe vdelane ukazne lupine z uporabo deklaracije lupine bash za obseg vrednosti (od vrednosti..do vrednosti). #!/bin/bash za števec v (1..20) izvede štetje odmevov od 1 do 20, trenutna vrednost $counter spanje 1 končano

Ta zanka for uporablja mehanizem za iskanje datotek po vzorcu (izveden kot del mehanizma za razširitev ukazov). Če so zgornja navodila objavljena neposredno v ukazna vrstica, bo deloval podobno. kahlan@solexp11$ ls count.ksh go.ksh kahlan@solexp11$ za datoteko v *.ksh ; do cp $file $file.backup ; končano kahlan@solexp11$ ls count.ksh count.ksh.backup go.ksh go.ksh.backup

medtem ko zanka

Spodaj je preprost primer uporabe zanke while. i=100; medtem ko [ $i -ge 0 ] ; do echo Odštevanje od 100 do 0, trenutna vrednost $i; naj--; Končano

Neskončne zanke je mogoče implementirati z deklaracijami while true ali while:, pri čemer je simbol: enakovreden manjkajoči operaciji v lupini Korn in bash. #!/bin/ksh # neskončna zanka while: do echo hello sleep 1 done

Do zanke

Spodaj je preprost primer uporabe zanke do. naj i=100; do [$i -le 0]; do echo Odštevanje od 100 do 1, trenutna vrednost $i; naj--; Končano

Vaja: Preizkusi in zanke v skriptih

3. Razvijte skript, ki bo uporabljal zanko while za štetje od 3 do 7.

4. Razvijte skript, ki bo za odštevanje od 8 do 4 uporabljal zanko dokler.

5. Razvijte skript, ki bo štel datoteke s pripono .txt v trenutnem imeniku.

6. Uporabite stavek if v ustvarjenem skriptu, da zagotovite pravilno delovanje, če v trenutnem imeniku ni datotek s pripono .txt.

Pravilen postopek za dokončanje praktične naloge: preverjanja in zanke v skriptah

1. Razvijte skript, ki bo uporabljal zanko for za štetje od 3 do 7.

#!/bin/bash for i in 3 4 5 6 7 do echo Štetje od 3 do 7, trenutna vrednost $i končano

2. Razvijte skript, ki bo uporabljal zanko for za štetje od 1 do 17000.

Lupina bash podpira zanke for, ki vam omogočajo ponavljanje zaporedij vrednosti. Tako je osnovna struktura takšni cikli:

Za var na seznamu naredi ukaz opravljen
V vsaki ponovitvi zanke bo spremenljivka var zapisana v naslednjo vrednost iz seznam. Prvi prehod zanke bo torej uporabil prvo vrednost s seznama. V drugem - drugi in tako naprej - dokler zanka ne doseže zadnjega elementa.

Ponavljanje preprostih vrednosti

Morda je najenostavnejši primer zanke for v skriptih bash ponavljanje po seznamu preprostih vrednosti:

#!/bin/bash for var in first second third fourth fifth do echo Element $var done
Rezultati tega skripta so prikazani spodaj. Jasno lahko vidite, da spremenljivka $var zaporedno vsebuje elemente s seznama. To se dogaja, dokler cikel ne doseže zadnjega od njih.


Preprosta for zanka

Upoštevajte, da spremenljivka $var ob izhodu iz zanke ohrani svojo vrednost, njeno vsebino je mogoče spremeniti in na splošno lahko z njo delate kot z vsako drugo spremenljivko.

Ponavljanje kompleksnih vrednosti

Seznam, ki se uporablja za inicializacijo zanke for, lahko vsebuje ne samo preproste nize, sestavljene iz ene besede, ampak tudi celotne fraze, ki vsebujejo več besed in ločil. Na primer, lahko izgleda takole:

#!/bin/bash for var in first "the second" "the third" "Jaz bom to naredil" do echo "This is: $var" done
To se zgodi, ko gre ta zanka skozi seznam. Kot lahko vidite, je rezultat precej pričakovan.


Ponavljanje kompleksnih vrednosti
TNW-CUS-FMP - promocijska koda za 10% popust na naše storitve, na voljo za aktivacijo v 7 dneh"

Inicializacija zanke s seznamom, pridobljenim iz rezultatov ukaza

Drug način za inicializacijo zanke for je, da ji posredujete seznam, ki je rezultat ukaza. Tukaj se uporablja zamenjava ukazov za njihovo izvajanje in pridobivanje rezultatov njihovega dela.

#!/bin/bash file="myfile" for var in $(cat $file) do echo " $var" done
Ta primer uporablja ukaz cat, ki bere vsebino datoteke. Nastali seznam vrednosti se prenese v zanko in prikaže na zaslonu. Upoštevajte, da datoteka, do katere dostopamo, vsebuje seznam besed, ločenih z novimi vrsticami; presledki niso uporabljeni.


Zanka, ki kroži po vsebini datoteke

Pri tem moramo upoštevati, da takšen pristop, če pričakujemo vrstično obdelavo podatkov, ne bo deloval za datoteko bolj kompleksne strukture, katere vrstice lahko vsebujejo več besed, ločenih s presledki. Zanka bo obdelala posamezne besede, ne vrstic.

Kaj pa, če to sploh ni tisto, kar potrebujete?

Ločila polj

Razlog za zgornjo lastnost je posebnost spremenljivka okolja, ki se imenuje IFS (Internal Field Separator) in omogoča določanje ločil polj. Lupina bash privzeto obravnava naslednje znake kot ločila polj:
  • Vesolje
  • Tabulatorski znak
  • Znak za pomik vrstice
Če bash v podatkih naleti na katerega od teh znakov, predpostavlja, da je pred njim naslednja neodvisna vrednost na seznamu.

Če želite odpraviti težavo, lahko začasno spremenite spremenljivko okolja IFS. Tukaj je opisano, kako to storite v skriptu bash, ob predpostavki, da potrebujete samo novo vrstico kot ločilo polj:

IFS=$"\n"
Ko dodate ta ukaz svojemu skriptu bash, bo deloval po pričakovanjih, pri čemer bo prezrl presledke in zavihke ter obravnaval samo znake nove vrstice kot ločila polj.

#!/bin/bash file="/etc/passwd" IFS=$"\n" for var in $(cat $file) do echo " $var" done
Če se ta skript zažene, bo izpisal točno to, kar se od njega zahteva, in v vsaki ponovitvi zanke omogočil dostop do naslednje vrstice, zapisane v datoteko.


Prehod datoteke po vrstici v zanki for

Ločila so lahko tudi drugi znaki. Na primer, zgoraj smo prikazali vsebino datoteke /etc/passwd. Uporabniški podatki v vrsticah so ločeni z dvopičji. Če morate take nize obdelati v zanki, lahko IFS konfigurirate takole:

Premikanje po datotekah v imeniku

Ena najpogostejših uporab zank for v skriptih bash je prečkanje datotek v imeniku in obdelava teh datotek.

Tukaj je na primer, kako našteti datoteke in mape:

#!/bin/bash za datoteko v /home/likegeeks/* do if [ -d "$file" ] then echo "$file je imenik" elif [ -f "$file" ] then echo "$file je datoteka" končano
Če ste razumeli prejšnje gradivo v tej seriji člankov, bi morali razumeti strukturo konstrukcije if-then, pa tudi, kako razlikovati datoteko od mape. Če težko razumete zgornjo kodo, ponovno preberite to gradivo.

To bo izpisal skript.


Prikaz vsebine mape

Bodite pozorni na to, kako inicializiramo zanko, namreč nadomestni znak"*" na koncu naslova mape. Ta simbol si lahko predstavljamo kot nadomestni znak, ki pomeni: "vse datoteke s poljubnimi imeni." vam omogoča organiziranje avtomatska zamenjava imena datotek, ki ustrezajo vzorcu.

Ko testiramo pogoj v stavku if, ime spremenljivke damo v narekovaje. To je storjeno, ker lahko ime datoteke ali mape vsebuje presledke.

Zanke v slogu C

Če ste seznanjeni s programskim jezikom C, se vam sintaksa za opis zank bash morda zdi čudna, saj ste očitno navajeni opisovati zanke na ta način:

Za (i = 0; i< 10; i++) { printf("number is %d\n", i); }
V skriptih bash lahko uporabite zanke for, katerih opis je zelo podoben zankam v slogu C, čeprav obstajajo nekatere razlike. Diagram cikla s tem pristopom izgleda takole:

For ((začetna vrednost spremenljivke; pogoj za zaključek zanke; sprememba spremenljivke))
V bash se lahko zapiše takole:

Za ((a = 1; a< 10; a++))
Tukaj je delujoč primer:

#!/bin/bash for ((i=1; i<= 10; i++)) do echo "number is $i" done
Ta koda bo izpisala seznam številk od 1 do 10.

Looping v slogu C

medtem ko zanka

Konstrukcija for ni edini način za organiziranje zank v bash skriptih. Tukaj lahko uporabite tudi zanke while. V takšni zanki lahko podate ukaz za preverjanje določenega pogoja in izvajate telo zanke, dokler pogoj, ki se testira, ne vrne nič ali signala za uspešno dokončanje določene operacije. Ko pogoj zanke vrne vrednost, ki ni enaka nič, kar pomeni napako, se bo zanka ustavila.

Tukaj je diagram organizacije medtem ko zank
med ukazom za preverjanje stanja
narediti
druge ekipe
Končano

Oglejmo si primer skripta z zanko, kot je ta:

#!/bin/bash var1=5 while [ $var1 -gt 0 ] do echo $var1 var1=$[ $var1 - 1 ] done
Na vstopu v zanko se preveri, ali je spremenljivka $var1 večja od nič. Če je tako, se izvede telo zanke, v kateri se ena odšteje od vrednosti spremenljivke. To se zgodi v vsaki ponovitvi in ​​natisnemo vrednost spremenljivke na konzolo, preden se spremeni. Takoj ko $var1 doseže vrednost 0, se zanka ustavi.

Rezultat zanke while

Če ne spremenite spremenljivke $var1, bo skript končal v neskončni zanki.

Ugnezdene zanke

V telesu zanke lahko uporabite kateri koli ukaz, vključno z zagonom drugih zank. Takšne konstrukcije imenujemo ugnezdene zanke:

#!/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
Spodaj je prikazano, kaj bo ta skript izpisal. Kot lahko vidite, se najprej izvede prva ponovitev zunanje zanke, nato tri ponovitve notranje, po njenem zaključku spet pride v poštev zunanja zanka, nato spet notranja.

Ugnezdene zanke

Obdelava vsebine datoteke

Najpogosteje se za obdelavo datotek uporabljajo ugnezdene zanke. Torej, zunanja zanka ponavlja vrstice datoteke, notranja pa že dela z vsako vrstico. Takole je na primer videti obdelava datoteke /etc/passwd:

#!/bin/bash IFS=$"\n" za vnos v $(cat /etc/passwd) do echo "Vrednosti v $entry –" IFS=: za vrednost v $entry do echo "$value" done Končano
V tem skriptu sta dve zanki. Prvi prečka vrstice z uporabo znaka nove vrstice kot ločila. Notranji je zaposlen z razčlenjevanjem nizov, katerih polja so ločena z dvopičjem.

Obdelava podatkov datoteke

Ta pristop je mogoče uporabiti pri obdelavi datotek CSV ali podobnih datotek, tako da ločilni znak po potrebi zapišete v spremenljivko okolja IFS.

Upravljanje cikla

Morda boste morali po vstopu v zanko ustaviti, ko spremenljivka zanke doseže določeno vrednost, ki ne ustreza prvotno podanemu pogoju za zaključek zanke. Ali bo v takšni situaciji treba počakati na normalen zaključek cikla? Seveda ne in v takih primerih bosta prav prišla naslednja dva ukaza:
  • odmor
  • nadaljevati

prekiniti ukaz

Ta ukaz vam omogoča, da prekinete izvajanje zanke. Uporablja se lahko za zanke for in while:

#!/bin/bash for var1 in 1 2 3 4 5 6 7 8 9 10 do if [ $var1 -eq 5 ] then break fi echo "Number: $var1" done
Takšna zanka bo v normalnih pogojih šla skozi celoten seznam vrednosti s seznama. Vendar pa bo v našem primeru njegovo izvajanje prekinjeno, ko bo spremenljivka $var1 enaka 5.

Zgodnji izhod iz zanke for

Tukaj je ista stvar, vendar za zanko while:

#!/bin/bash var1=1 while [ $var1 -lt 10 ] do if [ $var1 -eq 5 ] then break fi echo "Iteracija: $var1" var1=$(($var1 + 1)) done
Ukaz break, ki se izvede, ko $var1 doseže 5, prekine zanko. Konzola bo prikazala isto stvar kot v prejšnjem primeru.

nadaljuj ukaz

Ko se ta ukaz pojavi v telesu zanke, se trenutna ponovitev konča predčasno in se začne naslednja, ne da bi zapustili zanko. Poglejmo ukaz za nadaljevanje v zanki for:

#!/bin/bash for ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
Ko je pogoj znotraj zanke izpolnjen, to je, ko je $var1 večji od 5 in manjši od 10, lupina izvede ukaz za nadaljevanje. Posledica tega je preskok preostalih ukazov v telesu zanke in prehod na naslednjo ponovitev.

Ukaz za nadaljevanje v zanki for

Obdelava izhoda teče v zanki

Izhodne podatke iz zanke je mogoče obdelati bodisi s preusmeritvijo izhodnih podatkov bodisi s posredovanjem v cevovod. To storite tako, da za stavkom done dodate ukaze za obdelavo izhoda.

Na primer, namesto da na zaslonu prikažete, kaj je izhod v zanki, lahko vse to zapišete v datoteko ali posredujete nekam drugam:

#!/bin/bash za ((a = 1; a< 10; a++)) do echo "Number is $a" done >myfile.txt echo "končano."
Lupina bo ustvarila datoteko myfile.txt in preusmerila izhod stavka for v to datoteko. Odprimo datoteko in se prepričajmo, da vsebuje točno to, kar pričakujemo.

Preusmeri izhod zanke v datoteko

Primer: Iskanje izvršljivih datotek

Uporabimo že napisano in napišimo kaj koristnega. Na primer, če morate ugotoviti, katere izvedljive datoteke so na voljo v sistemu, lahko pregledate vse mape, zabeležene v spremenljivki okolja PATH. Celoten arzenal orodij, ki jih potrebujemo za to, že imamo, le sestaviti moramo vse skupaj:

#!/bin/bash IFS=: za mapo v $PATH do echo "$folder:" za datoteko v $folder/* do if [ -x $file ] then echo " $file" fi done done
Ta skript, majhen in preprost, nam je omogočil pridobitev seznama izvedljivih datotek, shranjenih v mapah iz PATH.

Iskanje izvedljivih datotek v mapah s spremenljivko PATH

Rezultati

Danes smo govorili o zankah for in while v skriptih bash, o tem, kako jih zagnati in kako jih upravljati. Zdaj veste, kako obdelati nize z različnimi ločili v zankah, veste, kako preusmeriti izhod podatkov v zankah v datoteke, kako si ogledati in analizirati vsebino imenikov.

Če predpostavimo, da ste razvijalec bash skriptov, ki o njih veste le tisto, kar je navedeno v prvem delu te serije člankov in v tem drugem, potem že lahko napišete kaj uporabnega. Pred nami je tretji del, po razumevanju katerega se boste naučili, kako posredovati parametre in stikala ukazne vrstice bash skriptom in kaj storiti z vsem tem.

Kratek opis razlike v vrstah zank:

for - bo izvedel dejanje, dokler obstajajo predmeti za izvedbo (na primer branje toka iz stdin, datoteke ali funkcije);
medtem ko - izvede dejanje dokler stanje je res;
dokler - se bo izvajalo, dokler stanje ne bo postalo res, tj. za zdaj je lažno.

ZA zanka

Oglejmo si to različico skripta z zanko:

$ cat loop.sh #!/bin/bash za spremenljivko v `ls -1` do echo "$variable" done

Sintaksa je zelo preprosta in je precej jasno prikazana v primeru:

for (začeti zanko) spremenljivka (deklarirati spremenljivko, na kateri bomo izvajali dejanja) in (pošlji tok v zanko) `ls -1` (ukaz, ki ga je treba izvesti in posredovati spremenljivki $variable). Do in done sta »telo« zanke, znotraj katerega se bodo izvajala glavna dejanja na prejetih podatkih, echo »$variable« pa je dejansko dejanje, ki ga izvaja zanka.

Zdaj pa malce spremenimo primer in namesto eksplicitnega podajanja ukaza bomo uporabili drugo spremenljivko:

$ cat loop.sh #!/bin/bash ls=`ls -1` za spremenljivko v $ls do echo "$variable" done

Zdaj je ukaz ls -1 posredovan v ločeni spremenljivki, kar vam omogoča bolj prilagodljivo delo z zanko. Namesto spremenljivke v zanki lahko uporabite tudi funkcijo:

$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) za spremenljivko v `lsl` do echo "$variable" done

Glavni pogoj zanke for je, da se bo izvajala, dokler ukaz, ki ji je bil posredovan, vsebuje objekte za dejanje. Na podlagi zgornjega primera - dokler ima ls -1 datoteke za prikaz - jih bo zanka posredovala spremenljivki in izvedla "telo zanke". Takoj ko se seznam datotek v imeniku konča, bo zanka zaključila svojo izvedbo.

Naredimo primer nekoliko bolj zapleteno.

Imenik vsebuje seznam datotek:

$ ls -1 datoteka1 datoteka2 datoteka3 datoteka4 datoteka5 loop.sh nofile1 nofile2 nofile3 nofile4 nofile5

Izmed njih moramo izbrati samo tiste, ki nimajo besede " št«:

$ cat loop.sh #!/bin/bash lsl=`ls -1` za spremenljivko v $lsl do echo "$variable" | grep -v "ne" končano $ ./loop.sh datoteka1 datoteka2 datoteka3 datoteka4 datoteka5 loop.sh

Pogojne izraze lahko uporabite tudi v zanki ( pogojni izrazi) […] za preverjanje pogojev in stavek break za prekinitev zanke, če se pogoj sproži.

Razmislite o tem primeru:

$ cat loop.sh #!/bin/bash lsl=`ls -1` za spremenljivko v $lsl do if [ $variable != "loop.sh" ] then echo "$variable" | grep -v "no" else break fi done

Zanka se bo nadaljevala, dokler ne naletite na datoteko loop.sh. Takoj, ko izvajanje zanke doseže to datoteko, bo zanka prekinjena z ukazom break:

$ ./loop.sh datoteka1 datoteka2 datoteka3 datoteka4 datoteka5

Drug primer je uporaba aritmetičnih operacij tik pred izvedbo telesa zanke:

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

Tukaj nastavimo tri nadzorne ukaze - count=1, krmilni pogoj - medtem ko je count manj kot 11 in ukaz za izvedbo - count +1:

WHILE in UNTIL zanki

Preprost primer, ki jasno prikazuje, kako deluje zanka while:

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

Spremenljivko $count nastavimo na nič, nato pa zaženemo zanko whi le s pogojem "dokler je $count manjše od deset, izvedi zanko." V telesu zanke, ki jo izvajamo postfiksni prirastek+1 spremenljivki $count in rezultat se natisne v stdout.

Rezultat izvedbe:

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

Takoj ko je vrednost spremenljivke $count postala 10, se je zanka ustavila.

Dober primer "neskončne" zanke, ki prikazuje, kako deluje 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

Zanka do deluje podobno, vendar v nasprotni smeri:

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

Tukaj nastavimo podoben pogoj, vendar namesto "medtem ko je spremenljivka manjša od 10", podamo "dokler spremenljivka ne postane večja od 10." Rezultat izvedbe:

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

Če se zgornji primer »neskončne zanke« izvede z uporabo until, ne bo izpisal ničesar, za razliko od while:

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

Ker " stanje"originalno" prav"—telo zanke ne bo izvedeno.

Tako kot v zanki for lahko uporabite funkcije v while in until. Na primer zanka iz resničnega skripta, ki preverja stanje strežnika Tomcat(PID je vzet iz sistema SLES, se lahko razlikuje v drugih sistemih), nekoliko poenostavljena različica:

$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) medtem ko check_tomcat_status do if [ -n "$ RUN" ] then printf "OPOZORILO: Tomcat še vedno deluje s PID $RUN." else printf "Tomcat ustavljen, nadaljuje...nn" break fi done

Rezultat izvedbe:

$ ./loop.sh OPOZORILO: Tomcat še vedno deluje s PID 14435 26548. OPOZORILO: Tomcat še vedno deluje s PID 14435 26548. OPOZORILO: Tomcat še vedno deluje s PID 14435 26548. OPOZORILO: Tomcat še vedno deluje s PID 14435 26548. OPOZORILO: Tomcat še vedno deluje s PID 14435 26548. OPOZORILO: Tomcat še vedno deluje s PID 14435 26548. OPOZORILO: Tomcat še vedno deluje s PID 14435 26548. OPOZORILO: Tomcat še vedno deluje s PID 14435

Celotna različica:

Check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) medtem ko check_tomcat_status; do if [ -n "$RUN" ] then printf "OPOZORILO: Tomcat še vedno deluje s PID $RUN. Ustavi ga? " answer "Zaustavljanje Tomcata ..." "Nadaljevanje namestitve ..." && $CATALINA_HOME/bin/shutdown sh 2&>1 /dev/null || prekinitev spanja 2 if [ -n "$RUN" ] then printf "Tomcat še vedno teče. Ubiti ga? " answer "Ubijanje Tomcata..." "Nadaljevanje namestitve...n" && ubiti $RUN || break sleep 2 fi else printf "Tomcat ustavljen, nadaljuje...nn" break fi done

Funkcija odgovora je bila opisana v članku, tukaj pa je uporabljena nekoliko izboljšana različica:

Odgovor () ( med branjem odgovora; naredi echo case $response v |) printf "$1n" return 0 break ;; |) printf "$2n" vrne 1 prelom ;; *) printf "Prosimo, vnesite Y(yes) ali N(ne)!" esac done )

Tu je bilo možno uporabiti medtem in dokler - vendar ne zanke for, saj bi for deloval enkrat (prejel PID in končal).

Zanke so izjemno priročna stvar pri pisanju kakršnih koli programov ali skriptov, prej celo nujna. Omogočajo nam, da določen del kode izvedemo določeno število krat. Seveda ima bash več vrst zank. Opisali bomo cikle za v, za, medtem ko, dokler. Čeprav za in in for veljata za različni sintaksi istega stavka, se po mojem mnenju razlikujeta med seboj bolj kot while od do.

Zanka s števcem za notr:

Cikel za v To je zanka s števcem. Blok kode, ki se nahaja v telesu zanke, se ponovi tolikokrat, kolikor je vrednosti na seznamu operatorja for in, pri vsaki ponovitvi pa spremenljivka števca (tukaj se imenuje var, a seveda lahko ga imenujete kakor koli želite) ima vrednost naslednjega elementa seznama.
Če je ključna beseda do v isti vrstici kot beseda for, morate za seznamom argumentov (pred do) postaviti podpičje.
Vsak od elementov<список>lahko vsebuje več argumentov. To je uporabno pri obdelavi skupin parametrov. V tem primeru za prisilno razčlenjevanje vsakega od argumentov v<списке>, morate uporabiti nastavljeno navodilo
Spremenljivko lahko uporabite kot seznam v zanki for.
IN<списке>Zanka for lahko uporablja imena datotek, ki lahko vsebujejo nadomestne znake. To je lahko zelo koristno pri delu z velikim številom datotek.
če<список>ni podan v zanki for, potem se spremenljivka $@ uporabi kot - seznam argumentov ukazne vrstice.
Pri ustvarjanju seznama argumentov lahko uporabite zamenjavo ukazov v zanki for.
Izhod zanke je mogoče preusmeriti iz stdout-a v datoteko ali kam drugam (več o tem lahko izveste, če pogledate V/I preusmeritev).

Sintaksa:
za var in<список>
narediti
<выполняемые команды>
Končano

primer:
za imena v ime1 ime2 ime3 ime4
narediti
echo $names
Končano

Operator zanke za ima drug način pisanja - zelo podoben sintaksi operatorja for v jeziku C. V tem primeru se pri inicializaciji števcev nastavijo začetne vrednosti spremenljivk ali ene spremenljivke in po vsakem prehodu zanke pogoj je preverjeno, če preverjanje vrne true, se začne naslednji prehod zanke. V bloku<приращение счётчиков>vrednost naših števcev spremenljivk se mora nujno spremeniti (ne nujno navzgor), tako da pri preverjanju pogoja prej ali slej dobimo vrednost false, sicer se zanka nikoli ne konča. Zelo priročna in kar je najpomembnejše poznana možnost, če je treba katero koli operacijo ponoviti določeno število krat.

S podobno sintakso:
za ((<инициализация счётчиков>; <проверка условия>; <приращение счётчиков>))
narediti
<выполняемые команды>
Končano

primer:
za ((var=1; var<= LIMIT ; var++))
narediti
echo $var
Končano

medtem ko zanka:

To je dokaj preprosta konstrukcija, ki preverja stanje za operaterjem medtem in če je ta pogoj resničen, izvede blok ukazov med besedama do in done in nato ponovno nadaljuje s preverjanjem pogoja. Če preverjanje vrne false, se cikel konča in začnejo se izvajati naslednji ukazi: Končano. To je nujno zagotoviti<проверка условия>odvisno od kode, ki se izvaja v zanki; sicer, če se rezultat preverjanja ne spremeni, boste dobili neskončno zanko.
Standardno vhodno napravo za zanko while je mogoče preusmeriti v datoteko z ukazom za preusmeritev< в конце цикла.

Sintaksa:
medtem<Проверка условия>
narediti
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
Končano

primer:
medtem ko [ $var0 -eq 100 ]
narediti
echo $var
var++
Končano

Operater medtem ima lahko več pogojev. Toda le zadnji od njih določa možnost nadaljevanja cikla. V tem primeru bo sintaksa operaterja zanke drugačna od običajne.
Sintaksa(Še enkrat ponavljam, da samo zadnji pogoj vpliva na izvedbo zanke) :
medtem
<условие1>
<условие2>

<условиеN>
narediti
<выполняемые команды - тело цикла>
Končano

Do zanke:

Operater dokler je zelo podoben medtem, prav tako ovrednoti pogoj, vendar izvede telo zanke, če je rezultat izračuna napačen. Morda se zdi nenavadno, vendar dokler ne oceni pogoja pred prvim prehodom zanke, na primer medtem, in ne po njem. Tako kot pri zankah for/in, morate pri postavljanju ključne besede do v isto vrstico kot deklaracija zanke vstaviti znak ";". pred storiti.
Kot v prejšnjem primeru je pomembno vedeti, da mora biti pogoj odvisen od operacij v telesu zanke, sicer se naš skript ne bo nikoli dokončal.

Sintaksa:
dokler<Проверка условия>
narediti
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
Končano

primer:
until [ $var0 -gt 100] # Pogoj se preveri na začetku ponovitve.
narediti
echo $var
var--
Končano

To je verjetno dovolj za zdaj. :)

  • Nazaj
  • Naprej

Novi članki:

  • Odkrivanje omrežja se ne vklopi v sistemu Windows 7/8/2008/2012
  • Napaka: Te aplikacije ni bilo mogoče zagnati, ker ni mogla najti ali naložiti vtičnika platforme Qt "windows".
  • Konfiguriranje samodejnega ponovnega zagona delovnih procesov rphost.exe na strežniku 1C 8.3
  • Kako zmanjšati velikost dnevnika transakcij (.ldf) v MS SQL 2008/20012

    MS SQL, tako kot vsak spodoben industrijski DBMS, skupaj z bazo podatkov vodi dnevnike transakcij, ki vam omogočajo, da povrnete stanje ...

0 Meeran Bala-Kumaran

Resnično poskušam razumeti, zakaj se ta zanka while nikoli ne konča, ko se zanka začne, je moja spremenljivka LOC nastavljena na Testing/, kar je imenik, ki sem ga ustvaril za testiranje tega programa, in ima naslednjo postavitev:

Želim, da se zanka konča, ko je za vse imenike uporabljena funkcija "štetje".
Evo, kar sem poskusil;

Preveril sem funkcijo štetja in ne ustvarja neskončne zanke

Poskušal sem zagnati algoritem ročno

PARSE=1 LOC=$LOC/ count AVAILABLEDIR=$(ls $LOC -AFl | sed "1 d" | grep "/$" | awk "( print $9 )"), medtem ko [ $PARSE = "1" ] naredi če [[ $(AVAILABLEDIR[@]) == "" ]]; nato PARSE=0 fi DIRBASE=$LOC za a v $(AVAILABLEDIR[@]); do LOC="$(DIRBASE)$(a)" LOCLIST="$LOCLIST $LOC" štetje opravljeno za v $(LOCLIST[@]); do TMPAVAILABLEDIR=$(ls $a -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") PREPEND=$a if [[ $(TMPAVAILABLEDIR[@]) == "" ] ]; nato nadaljujte fi za a v $(TMPAVAILABLEDIR[@]); do TMPAVAILABLEDIR2="$TMPAVAILABLEDIR2 $(PREPEND[@])$(a)" končano NEWAVAILABLEDIR="$NEWAVAILABLEDIR $TMPAVAILABLEDIR2" končano AVAILABLEDIR=$NEWAVAILABLEDIR NEWAVAILABLEDIR="" LOC="" končano

Resnično se trudim in vsak prispevek bi bil zelo cenjen, to sem poskušal ugotoviti zadnji dve uri.

bash neskončna zanka

4 odgovori

Poskusite zagnati skript z argumentom -x ali ga zapisati v prvo vrstico:

#!/bin/bash -x

Potem ti pove vse, kar počne.

V tem primeru boste morda opazili dve napaki:

    TMPAVAILABLEDIR2 nikoli ne naložite znova

    Na navadnih datotekah naredite tudi l.

Če se res morate izogniti rekurziji, poskusite to, popolnoma brez rekurzije:

#!/bin/bash count() ( echo counting "$1" ) todo=(Testiranje) medtem ko preizkusite $(#todo[@]) != 0 do doit=("$(todo[@])") todo= () za dir v "$(doit[@])" do za vnos v "$dir"/* # če je dir prazen, to prikaže vnos z imenom "*" do test -e "$entry" || nadaljuj # preskoči vnos "*" praznega imenika štetje "$entry" test -d "$entry" || nadaljuj todo+=("$entry") opravljeno opravljeno opravljeno

Vendar mi prosim povejte, zakaj ne morete uporabiti rekurzije? Je to kakšna alergija? Zaobljuba? Ali tam, kjer živite, obstajajo kakšni lokalni zakoni proti rekurzivni programski opremi?

Napisali ste, da želite izvesti "štetje" na vseh rezih. Preverite možnosti iskanja:

Poiščite $LOC -tip d | med branjem dir; do cd $LOC cd $(dir) count done

ali krajše (ko vaš števec funkcij vzame imenik kot parameter 1)

Poiščite $LOC -tip d | xargi štejejo

Zdaj vidim, da ne želite uporabiti find ali ls -R (rekurzivna funkcija). Potem bi morali narediti svojo lastno rekurzivno funkcijo, kot je

Funkcija parseDir ( ls -d */ $1 | med branjem imenika; štetje parseDir $1/$dir končano)

Ne vem, ali bo to delovalo, vendar je to zanimivo vprašanje, o katerem nisem mogel nehati razmišljati. Vso srečo

Medtem ko je res; naredi za besedo v "$(echo *)" ; do if [[ -d "$word" ]] ; nato d[$((i++))]="$PWD"/"$word" elif [[ -f "$word" ]] ;potem f[$((j++))]="$PWD"/"$ beseda" fi narejeno [[ $k -gt $i ]] && cd .. cd "$d[$((k++))]" || odmor narejen