Bezgalīga kamēr cilpa BASH skriptā. BASH: for, while, līdz cilpu apraksts un lietošanas piemēri Piemērs: izpildāmo failu meklēšana


Autors: Pols Kobauts
Publicēšanas datums: 2014. gada 16. oktobris
Tulkojums: A. Panin
Tulkošanas datums: 2014. gada 21. decembris

22. nodaļa. Cilpas skriptos

testa komanda

Testa komanda ļauj noteikt, vai izteiksme ir patiesa vai nepatiesa. Sāksim ar testēšanu, vai vesela skaitļa vērtība 10 ir lielāka par vesela skaitļa vērtību 55. $ tests 10 -gt 55 ; atbalss $? 1 $

Testa komanda atgriež 1, ja izteiksme ir nepatiesa. Un, kā redzēsit nākamajā piemērā, testa komanda atgriezīs 0, ja izteiksme tiek novērtēta kā patiesa. $ tests 56 -gt 55 ; atbalss $? 0 $

Ja jums ir ērtāk strādāt ar virknēm true un false, varat izmantot testa komandu, kā parādīts tālāk. $ test 56 -gt 55 && echo true || echo false true $ test 6 -gt 55 && echo true || atbalss viltus nepatiess

Testa komandu var aizstāt arī ar kvadrātiekavām, tāpēc komandas zemāk esošajā piemērā ir tieši tādas pašas kā komandas iepriekš minētajā piemērā. $ [ 56 -gt 55 ] && echo true || echo false true $ [ 6 -gt 55 ] && echo true || atbalss viltus nepatiess

Tālāk ir sniegti dažu pārbaužu ieviešanas piemēri. Skatiet man testa lapu, lai iegūtu pārskatu par papildus iespējas dažādu pārbaužu veikšana. [ -d foo ] Vai direktorijs foo pastāv? [-e bar] Vai joslas fails pastāv? [ "/etc" = $PWD] Vai /etc ir līdzvērtīgs $PWD vērtībai? [ $1 != "secret" ] Vai pirmā skripta parametra vērtība atšķiras no slepenās virknes? [ 55 -lt $bar ] Vai vesela skaitļa vērtība 55 ir mazāka par $bar vērtību? [$foo -ge 1000] Vai $foo vērtība ir lielāka vai vienāda ar veselu skaitļa vērtību 1000? ["abc"< $bar ] Будет ли строка abc расположена выше значения переменной $bar в списке после сортировки? [ -f foo ] Является ли foo обычным файлом? [ -r bar ] Является ли bar lasāms fails? [ foo -nt bar ] Vai foo ir jaunāks par bāru ? [-o nounset] Vai ir iespējota nounset apvalka opcija?

Čeku operatorus var apvienot ar operatoriem, kas atbilst loģiskās operācijas"UN" un "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 viltus patiess

Nosacīts lēciens, ja tad citādi

Konstrukcija if then else ir paredzēta, lai atlasītu koda opciju. Ja noteikts nosacījums ir patiess, tiks izpildīts kāds kods, pretējā gadījumā tiks izpildīts kāds cits kods. Tālāk sniegtajā piemērā tiek pārbaudīta faila esamība, pēc tam, ja tiek apstiprināts pieņēmums par faila esamību, tiek parādīts atbilstošs ziņojums. #!/bin/bash ja [ -f isit.txt ] tad atkārto, ka fails isit.txt eksistē! citādi echo fails isit.txt nav atrasts! fi

Gadījumā, ja mēs ietaupīsim šo kodu skriptu failā ar nosaukumu "choice", to var izpildīt tādā pašā veidā. $ ./choice fails isit.txt nav atrasts! $ touch isit.txt $ ./choice fails isit.txt pastāv! $

Nosacīts lēciens ja tad elifs

Jūs varat izlikt jauns operators nosacīts lēciens, ja atrodas else blokā, izmantojot elif operatoru. Zemāk ir vienkāršs šāda ieraksta piemērs. #!/bin/bash count=42 ja [ $count -eq 42 ], tad atbalss "42 ir derīga vērtība." elif [ $count -gt 42 ] tad atbalsi "Pārāk daudz." else echo "Nepietiek." fi

cilpai

Tālāk esošajā piemērā ir parādīta klasiskās cilpas sintakse bash čaulā. for i in 1 2 4 do echo $i done

Piemērs for cilpas izmantošanai kopā ar iekļautu čaulas izsaukumu. #!/bin/ksh skaitītājam `seq 1 20` veic atbalss skaitīšanu no 1 līdz 20, pašreizējā vērtība $counter miega 1 pabeigts

Skriptu, kas ir pilnīgi līdzīgs iepriekš parādītajam, var izveidot, neizmantojot iegulto komandu apvalku, izmantojot bash apvalka deklarāciju vērtību diapazonam (no vērtības.. līdz vērtībai). #!/bin/bash skaitītājam in (1..20) veic atbalss skaitīšanu no 1 līdz 20, pašreizējā vērtība $counter miegs 1 pabeigts

Šī cilpa izmanto mehānismu failu meklēšanai pēc modeļa (tiek ieviests kā daļa no komandas paplašināšanas mehānisma). Ja iepriekš minētie norādījumi ir ievietoti tieši komandrinda, tas darbosies līdzīgi. kahlan@solexp11$ ls count.ksh go.ksh kahlan@solexp11$ failam *.ksh ; do cp $fails $file.backup ; darīts kahlan@solexp11$ ls count.ksh count.ksh.backup go.ksh go.ksh.backup

kamēr cilpa

Tālāk ir sniegts vienkāršs kamēr cilpas izmantošanas piemērs. i=100; kamēr [ $i -ge 0 ] ; do echo Atpakaļskaitīšana no 100 līdz 0, pašreizējā vērtība $i; lai es--; darīts

Bezgalīgas cilpas var ieviest, izmantojot while true vai while: deklarācijas, kur simbols: ir ekvivalents trūkstošajai darbībai Korn apvalkā un bash. #!/bin/ksh # bezgalīga cilpa while: do echo hello sleep 1 done

Līdz cilpai

Tālāk ir sniegts vienkāršs līdz cilpas izmantošanas piemērs. pieņemsim i=100; līdz [ $i -le 0 ] ; do echo Atpakaļskaitīšana no 100 līdz 1, pašreizējā vērtība $i; lai es--; darīts

Prakse: testi un cilpas skriptos

3. Izstrādājiet skriptu, kas izmantos laika cilpu, lai skaitītu no 3 līdz 7.

4. Izstrādājiet skriptu, kurā tiks izmantota līdz cilpa, lai skaitītu atpakaļ no 8 līdz 4.

5. Izstrādājiet skriptu, kas pašreizējā direktorijā saskaitīs failus ar paplašinājumu .txt.

6. Izmantojiet if priekšrakstu izveidotajā skriptā, lai tas darbotos pareizi, ja pašreizējā direktorijā nav failu ar paplašinājumu .txt.

Pareiza praktiskā uzdevuma izpildes procedūra: pārbaudes un cilpas skriptos

1. Izstrādājiet skriptu, kas izmantos for cilpu, lai skaitītu no 3 līdz 7.

#!/bin/bash for i in 3 4 5 6 7 do echo Skaitīšana no 3 līdz 7, pašreizējā vērtība $i darīts

2. Izstrādājiet skriptu, kas izmantos for cilpu, lai skaitītu no 1 līdz 17000.

Bash apvalks atbalsta cilpas, kas ļauj atkārtot vērtību secības. Tā tas ir pamatstruktūrašādi cikli:

Var in list do komanda ir pabeigta
Katrā cilpas iterācijā mainīgais var tiks ierakstīts nākamajā vērtībā no sarakstu. Tāpēc cilpas pirmajā gājienā tiks izmantota pirmā vērtība no saraksta. Otrajā - otrajā un tā tālāk - līdz cilpa sasniedz pēdējo elementu.

Vienkāršu vērtību atkārtošana

Iespējams, vienkāršākais for cilpas piemērs bash skriptos ir atkārtošana vienkāršu vērtību sarakstā:

#!/bin/bash for var pirmajā otrajā trešajā ceturtajā piektajā do echo $var vienums ir pabeigts
Šī skripta rezultāti ir parādīti zemāk. Var skaidri redzēt, ka mainīgais $var satur elementus no saraksta secīgi. Tas notiek, līdz cikls sasniedz pēdējo no tiem.


Vienkāršs cilpai

Lūdzu, ņemiet vērā, ka mainīgais $var saglabā savu vērtību, izejot no cilpas, tā saturu var mainīt, un kopumā ar to var strādāt tāpat kā ar jebkuru citu mainīgo.

Sarežģītu vērtību atkārtošana

For cilpas inicializēšanai izmantotajā sarakstā var būt ne tikai vienkāršas virknes, kas sastāv no viena vārda, bet arī veselas frāzes, kas satur vairākus vārdus un pieturzīmes. Piemēram, tas varētu izskatīties šādi:

#!/bin/bash for var pirmajā "otrajā" "trešajā" "Es to izdarīšu" do echo "Tas ir: $var" darīts
Tas notiek pēc tam, kad šī cilpa iziet cauri sarakstam. Kā redzat, rezultāts ir diezgan gaidīts.


Sarežģītu vērtību atkārtošana
TNW-CUS-FMP - reklāmas kods 10% atlaidei mūsu pakalpojumiem, kas pieejams aktivizēšanai 7 dienu laikā"

Cilpas inicializācija ar sarakstu, kas iegūts no komandas rezultātiem

Vēl viens veids, kā inicializēt for cilpu, ir nodot tai sarakstu, kas ir komandas rezultāts. Šeit komandu aizstāšana tiek izmantota, lai tās izpildītu un iegūtu darba rezultātus.

#!/bin/bash file="myfile" for var in $(cat $file) do echo " $var" darīts
Šajā piemērā tiek izmantota komanda cat, kas nolasa faila saturu. Iegūtais vērtību saraksts tiek nodots cilpai un tiek parādīts ekrānā. Lūdzu, ņemiet vērā, ka failā, kuram mēs piekļūstam, ir vārdu saraksts, kas atdalīts ar jaunām rindiņām; atstarpes netiek izmantotas.


Cilpa, kas griežas cauri faila saturam

Šeit jāņem vērā, ka šāda pieeja, ja paredzama datu apstrāde rindiņā, nederēs sarežģītākas struktūras failam, kura rindās var būt vairāki ar atstarpēm atdalīti vārdi. Cilpa apstrādās atsevišķus vārdus, nevis rindas.

Ko darīt, ja tas nemaz nav tas, kas jums nepieciešams?

Lauku atdalītāji

Iepriekš minētās funkcijas iemesls ir īpašs vides mainīgais, ko sauc par IFS (Internal Field Separator) un ļauj norādīt lauku atdalītājus. Pēc noklusējuma bash apvalks šādas rakstzīmes uzskata par lauku atdalītājiem:
  • Kosmoss
  • Tabulēšanas rakstzīme
  • Rindas plūsmas raksturs
Ja bash datos atrod kādu no šīm rakstzīmēm, tiek pieņemts, ka pirms tās ir nākamā neatkarīgā vērtība sarakstā.

Lai atrisinātu problēmu, varat īslaicīgi mainīt IFS vides mainīgo. Lūk, kā to izdarīt bash skriptā, pieņemot, ka jums ir nepieciešama tikai jauna rindiņa kā lauka atdalītājs:

IFS=$"\n"
Kad pievienosiet šo komandu savam bash skriptam, tā darbosies kā paredzēts, ignorējot atstarpes un tabulēšanas zīmes un kā lauku atdalītājus apstrādājot tikai jaunas rindiņas rakstzīmes.

#!/bin/bash file="/etc/passwd" IFS=$"\n" for var in $(cat $file) do echo " $var" darīts
Ja šis skripts tiek palaists, tas izvadīs tieši to, kas no tā tiek prasīts, katrā cilpas iterācijā nodrošinot piekļuvi nākamajai failā ierakstītajai rindai.


Faila šķērsošana rindiņā pa rindiņai for cilpā

Atdalītāji var būt arī citas rakstzīmes. Piemēram, iepriekš mēs parādījām /etc/passwd faila saturu. Lietotāja dati rindās ir atdalīti ar koliem. Ja jums ir jāapstrādā šādas virknes cilpā, IFS var konfigurēt šādi:

Katalogā esošo failu pārvietošana

Viens no visizplatītākajiem for cilpu lietojumiem bash skriptos ir šķērsot failus, kas atrodas direktorijā, un apstrādāt šos failus.

Piemēram, šeit ir norādīts, kā uzskaitīt failus un mapes:

#!/bin/bash failam mapē /home/likegeeks/* do if [ -d "$file" ] then echo "$file is a directory" elif [ -f "$file" ] then echo "$file is a fails" ir pabeigts
Ja sapratāt iepriekšējo šīs rakstu sērijas materiālu, jums vajadzētu saprast konstrukcijas ja-tad struktūru, kā arī to, kā atšķirt failu no mapes. Ja jums ir grūti saprast iepriekš minēto kodu, vēlreiz izlasiet šo materiālu.

Tas ir tas, ko skripts izvadīs.


Mapes satura parādīšana

Pievērsiet uzmanību tam, kā mēs inicializējam cilpu, proti aizstājējzīme"*" mapes adreses beigās. Šo simbolu var uzskatīt par aizstājējzīmi, kas nozīmē: “visi faili ar jebkādiem nosaukumiem”. tas ļauj organizēt automātiska aizstāšana failu nosaukumi, kas atbilst modelim.

Pārbaudot nosacījumu if priekšrakstā, mainīgā nosaukumu ievietojam pēdiņās. Tas tiek darīts, jo faila vai mapes nosaukumā var būt atstarpes.

C-stils cilpām

Ja esat pazīstams ar C programmēšanas valodu, sintakse bash for loop aprakstam jums var šķist dīvaina, jo jūs acīmredzot esat pieradis cilpas aprakstīt šādi:

Ja (i = 0; i< 10; i++) { printf("number is %d\n", i); }
Bash skriptos varat izmantot cilpas, kuru apraksts izskatās ļoti līdzīgs C stila cilpām, lai gan ir dažas atšķirības. Cikla diagramma ar šo pieeju izskatās šādi:

For ((mainīgā sākuma vērtība; nosacījums cilpas beigu cilpai; mainīgā lieluma maiņa))
Bash to var rakstīt šādi:

For ((a = 1; a< 10; a++))
Šeit ir darba piemērs:

#!/bin/bash for ((i=1; i<= 10; i++)) do echo "number is $i" done
Šis kods izvadīs skaitļu sarakstu no 1 līdz 10.

Lopings C stilā

kamēr cilpa

For konstrukcija nav vienīgais veids, kā organizēt cilpas bash skriptos. Šeit varat izmantot arī kamēr cilpas. Šādā cilpā varat norādīt komandu, lai pārbaudītu noteiktu nosacījumu un izpildītu cilpas pamattekstu, līdz pārbaudāmais nosacījums atgriež nulli vai signālu par noteiktas darbības veiksmīgu pabeigšanu. Kad cilpas nosacījums atgriež vērtību, kas nav nulle, kas nozīmē kļūdu, cilpa apstāsies.

Šeit ir diagramma par while cilpu organizēšanu
kamēr stāvokļa pārbaudes komanda
darīt
citas komandas
darīts

Apskatīsim skripta piemēru ar šādu cilpu:

#!/bin/bash var1=5, kamēr [ $var1 -gt 0 ] veic atbalsi $var1 var1=$[ $var1 - 1 ] pabeigts
Pie ieejas cilpā tiek pārbaudīts, vai mainīgais $var1 ir lielāks par nulli. Ja tā, tiek izpildīts cilpas pamatteksts, kurā viens tiek atņemts no mainīgā vērtības. Tas notiek katrā iterācijā, un mēs izdrukājam mainīgā vērtību konsolē pirms tā modificēšanas. Tiklīdz $var1 sasniedz vērtību 0, cilpa apstājas.

Kamēr cilpas rezultāts

Ja nemodificēsit mainīgo $var1, skripts nonāks bezgalīgā ciklā.

Ligzdotas cilpas

Varat izmantot jebkuras komandas cilpas pamattekstā, tostarp citu cilpu palaišanu. Šādas konstrukcijas sauc par ligzdotām cilpām:

#!/bin/bash for ((a = 1; a<= 3; a++)) do echo "Start $a:" for ((b = 1; b <= 3; b++)) do echo " Inner loop: $b" done done
Tālāk ir norādīts, ko šis skripts izvadīs. Kā redzat, vispirms tiek izpildīta pirmā ārējās cilpas iterācija, pēc tam trīs iekšējās iterācijas, pēc tās pabeigšanas atkal spēlē ārējā cilpa, pēc tam atkal iekšējā.

Ligzdotas cilpas

Faila satura apstrāde

Visbiežāk failu apstrādei tiek izmantotas ligzdotas cilpas. Tātad ārējā cilpa atkārtojas pa faila rindām, un iekšējā jau darbojas ar katru rindiņu. Piemēram, lūk, kā izskatās /etc/passwd faila apstrāde:

#!/bin/bash IFS=$"\n" ierakstam $(cat /etc/passwd) do echo "Values ​​in $entry –" IFS=: for value in $entry do echo " $value" done darīts
Šajā skriptā ir divas cilpas. Pirmais šķērso līnijas, izmantojot jaunās rindiņas rakstzīmi kā atdalītāju. Iekšējā ir aizņemta parsējot virknes, kuru lauki ir atdalīti ar koliem.

Failu datu apstrāde

Šo pieeju var izmantot, apstrādājot CSV failus vai citus līdzīgus failus, pēc vajadzības ierakstot norobežotāja rakstzīmi IFS vides mainīgajā.

Cikla vadība

Iespējams, pēc cilpas ievadīšanas jums tas būs jāpārtrauc, kad cilpas mainīgais sasniegs noteiktu vērtību, kas neatbilst sākotnēji norādītajam cilpas beigu nosacījumam. Vai šādā situācijā būs jāgaida normāla cikla pabeigšana? Protams, nē, un šādos gadījumos noderēs šādas divas komandas:
  • pārtraukums
  • Turpināt

pārtraukuma komanda

Šī komanda ļauj pārtraukt cilpas izpildi. To var izmantot gan for, gan while cilpām:

#!/bin/bash for var1 in 1 2 3 4 5 6 7 8 9 10 do if [ $var1 -eq 5 ] then break fi echo "Numurs: $var1" darīts
Šāda cilpa normālos apstākļos iet cauri visam vērtību sarakstam no saraksta. Tomēr mūsu gadījumā tā izpilde tiks pārtraukta, ja mainīgais $ var1 ir vienāds ar 5.

Priekšlaicīga iziešana no for cilpas

Šeit ir tā pati lieta, bet īslaicīgai cilpai:

#!/bin/bash var1=1, kamēr [ $var1 -lt 10 ] do if [ $var1 -eq 5 ] then break fi echo "Iterācija: $var1" var1=$(($var1 + 1)) darīts
Pārtraukuma komanda, kas tiek izpildīta, kad $var1 sasniedz 5, pārtrauc cilpu. Konsole parādīs to pašu, ko iepriekšējā piemērā.

turpināt komandu

Kad šī komanda tiek sastapta cilpas pamattekstā, pašreizējā iterācija beidzas agri un sākas nākamā, neizejot no cilpas. Apskatīsim komandu turpināt cilpā:

#!/bin/bash for ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
Kad nosacījums cilpas iekšienē ir izpildīts, tas ir, ja $var1 ir lielāks par 5 un mazāks par 10, apvalks izpilda komandu turpināt. Tā rezultātā tiek izlaistas atlikušās komandas cilpas pamattekstā un tiek pāriets uz nākamo iterāciju.

Turpināšanas komanda for cilpā

Izvades apstrāde darbojas cilpā

Datus, kas izvadīti no cilpas, var apstrādāt, novirzot izvadi vai nododot to konveijeram. Tas tiek darīts, pievienojot izvades apstrādes komandas pēc pabeigtā paziņojuma.

Piemēram, tā vietā, lai ekrānā parādītu, kas tiek izvadīts cilpā, varat to visu ierakstīt failā vai nodot kaut kur citur:

#!/bin/bash for ((a = 1; a< 10; a++)) do echo "Number is $a" done >myfile.txt echo "pabeigts".
Apvalks izveidos failu myfile.txt un novirzīs priekšraksta izvadi uz šo failu. Atvērsim failu un pārliecināsimies, ka tajā ir tieši tas, ko mēs sagaidām.

Pārvirzīt cilpas izvadi uz failu

Piemērs: meklējiet izpildāmos failus

Izmantosim jau aprakstīto un uzrakstīsim ko noderīgu. Piemēram, ja jums ir jānoskaidro, kuri izpildāmie faili ir pieejami sistēmā, varat skenēt visas mapes, kas ierakstītas vides mainīgajā PATH. Mums jau ir viss šim nolūkam nepieciešamais rīku arsenāls, tikai tas viss ir jāsaliek kopā:

Nr.
Šis mazais un vienkāršais skripts ļāva mums iegūt izpildāmo failu sarakstu, kas saglabāti mapēs no PATH.

Izpildāmo failu meklēšana mapēs no mainīgā PATH

Rezultāti

Šodien mēs runājām par for un while cilpām bash skriptos, kā tās palaist un pārvaldīt. Tagad jūs zināt, kā cilpās apstrādāt virknes ar dažādiem norobežotājiem, zināt, kā cilpās izvadīto datu izvadi pāradresēt uz failiem, kā skatīt un analizēt direktoriju saturu.

Ja pieņemam, ka esat bash skriptu izstrādātājs, kurš par tiem zina tikai to, kas ir teikts šīs rakstu sērijas pirmajā daļā un šajā otrajā, tad jau varat uzrakstīt ko noderīgu. Priekšā ir trešā daļa, pēc kuras izpratnes jūs uzzināsit, kā nodot parametrus un komandrindas slēdžus bash skriptiem un ko ar to visu darīt.

Īss apraksts par cilpu veidu atšķirībām:

for - veiks darbību tik ilgi, kamēr ir izpildāmi objekti (piemēram, straumes nolasīšana no stdin, faila vai funkcijas);
kamēr - veic darbību līdz stāvokli ir patiess;
līdz - tiks izpildīts tik ilgi, cik stāvokli nekļūs par patiesību, t.i. pagaidām tas ir nepatiess.

FOR Loop

Apskatīsim šo skripta versiju ar cilpu:

$ cat loop.sh #!/bin/bash mainīgajam `ls -1` do echo "$variable" darīts

Sintakse ir ļoti vienkārša un ir diezgan skaidri parādīta piemērā:

for (sākt cilpu) mainīgais (deklarē mainīgo, ar kuru mēs veiksim darbības) in (nosūtīt plūsmu uz cilpu) `ls -1` (komanda, kas jāizpilda un jānodod mainīgajam $ mainīgajam). Do un done ir cilpas “ķermenis”, kurā tiks veiktas galvenās darbības ar saņemtajiem datiem, un atbalss “$mainīgais” ir cilpas faktiskā darbība.

Tagad nedaudz mainīsim piemēru, un tā vietā, lai skaidri norādītu komandu, mēs izmantosim otro mainīgo:

$ cat loop.sh #!/bin/bash ls=`ls -1` mainīgajam $ls do atbalss "$mainīgais" darīts

Tagad komanda ls -1 tiek nodota atsevišķā mainīgā, kas ļauj elastīgāk strādāt ar cilpu. Cilpas mainīgā vietā varat izmantot arī funkciju:

$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) mainīgajam `lsl` do echo "$variable" darīts

Galvenais for cilpas nosacījums ir tāds, ka tā tiks izpildīta tik ilgi, kamēr tai nodotā ​​komanda satur darbības objektus. Pamatojoties uz iepriekš minēto piemēru - ja vien ls -1 ir parādāmie faili, cilpa tos nodos mainīgajam un izpildīs "cilpas pamattekstu". Tiklīdz failu saraksts direktorijā beidzas, cilpa pabeigs tā izpildi.

Padarīsim piemēru nedaudz sarežģītāku.

Direktorijā ir failu saraksts:

$ ls -1 fails1 fails2 fails3 fails4 fails5 cilpa.sh nofile1 nofile2 nofile3 nofile4 nofile5

Mums no tiem jāatlasa tikai tie, kuriem nav vārda " «:

$ cat loop.sh #!/bin/bash lsl=`ls -1` mainīgajam $lsl do echo "$variable" | grep -v "nē" darīts $ ./loop.sh fails1 fails2 fails3 fails4 fails5 loop.sh

Varat arī izmantot nosacījuma izteiksmes cilpā ( nosacītās izteiksmes) […], lai pārbaudītu nosacījumus un pārtraukuma paziņojumu, lai pārtrauktu cilpu, ja nosacījums tiek aktivizēts.

Apsveriet šo piemēru:

$ cat loop.sh #!/bin/bash lsl=`ls -1` mainīgajam $lsl do if [ $variable != "loop.sh" ] then echo "$variable" | grep -v "nē" cits pārtraukums fi darīts

Cilpa turpināsies, līdz tiks atrasts fails loop.sh. Tiklīdz cilpas izpilde sasniedz šo failu, cilpa tiks pārtraukta ar pārtraukuma komandu:

$ ./loop.sh fails1 fails2 fails3 fails4 fails5

Vēl viens piemērs ir aritmētisko darbību izmantošana tieši pirms cilpas pamatteksta izpildes:

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

Šeit mēs iestatām trīs vadības komandas - count=1, kontroles nosacījumu - kamēr skaits ir mazāks par 11, un komandu izpildei - count +1:

WHILE un LĪDZ cilpas

Vienkāršs piemērs, kas skaidri parāda, kā darbojas cilpa while:

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

Mēs iestatām $count mainīgo uz nulli un pēc tam izpildām whi le cilpu ar nosacījumu “kamēr $count ir mazāks par desmit, izpildiet cilpu”. Cilpas korpusā mēs izpildām postfix pieaugums+1 mainīgajam $count, un rezultāts tiek izdrukāts uz stdout.

Izpildes rezultāts:

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

Tiklīdz mainīgā $count vērtība kļuva par 10, cilpa apstājās.

Labs "bezgalīgas" cilpas piemērs, kas parāda, kā darbojas kamēr:

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

Līdz cilpa darbojas līdzīgi, bet pretējā virzienā:

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

Šeit mēs iestatām līdzīgu nosacījumu, bet tā vietā, lai “kamēr mainīgais ir mazāks par 10”, mēs norādām “līdz mainīgais kļūst lielāks par 10”. Izpildes rezultāts:

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

Ja iepriekš minētais “bezgalīgas cilpas” piemērs tiek izpildīts, izmantojot līdz, tas neko neizvadīs, atšķirībā no kamēr:

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

Jo " stāvokli"sākotnēji" taisnība"— cilpas pamatteksts netiks izpildīts.

Tāpat kā for cilpā, varat izmantot funkcijas kamēr un līdz. Piemēram, cilpa no reālas dzīves skripta, kas pārbauda servera statusu Runcis(PID tiek ņemts no sistēmas SLES, citās sistēmās var atšķirties), nedaudz vienkāršota versija:

$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep runcis | grep -v grep | grep java | awk "(print $2)"` ), kamēr check_tomcat_status do if [ -n "$ RUN" ], tad printf "BRĪDINĀJUMS: Tomcat joprojām darbojas ar PID $RUN." else printf "Runcis apstājās, turpinās...nn" pārtraukums ir pabeigts

Izpildes rezultāts:

$ ./loop.sh BRĪDINĀJUMS: Tomcat joprojām darbojas ar PID 14435 26548. BRĪDINĀJUMS: Tomcat joprojām darbojas ar PID 14435 26548. BRĪDINĀJUMS: Tomcat joprojām darbojas ar PID 14435 26548. BRĪDINĀJUMS: Tomcat joprojām darbojas ar PIDcat8WARN3:2654. darbojas ar PID 14435 26548. BRĪDINĀJUMS: Tomcat joprojām darbojas ar PID 14435 26548. BRĪDINĀJUMS: Tomcat joprojām darbojas ar PID 14435 26548. BRĪDINĀJUMS: Tomcat joprojām darbojas ar PID 14435.

Pilna versija:

Check_tomcat_status () ( RUN=`ps aux | grep runcis | grep -v grep | grep java | awk "(print $2)"` ) kamēr check_tomcat_status; do if [ -n "$RUN" ] then printf "BRĪDINĀJUMS: Tomcat joprojām darbojas ar PID $RUN. Apturēt to? " atbildiet "Tomcat apturēšana..." "Notiek instalēšana..." && $CATALINA_HOME/bin/shutdown sh 2&>1 /dev/null || pārtraukt miegu 2 if [ -n "$RUN" ] then printf "Runcis joprojām darbojas. Nogalināt to? " atbilde "Killing Tomcat..." "Notiek instalēšana...n" && kill $RUN || pārtraukt miegu 2 fi else printf "Runcis apstājās, turpinās...nn" pārtraukums fi darīts

Atbildes funkcija tika aprakstīta rakstā, bet šeit tiek izmantota nedaudz uzlabota versija:

Atbilde () (nolasot atbildi; veikt atbalss gadījumu $response in |) printf "$1n" return 0 break ;; |) printf "$2n" atgriež 1 pārtraukumu ;; *) printf "Lūdzu, ievadiet Y(jā) vai N(nē)! " esac done )

Šeit bija iespējams izmantot gan while, gan līdz, bet ne for cilpu, jo for būtu darbojies vienu reizi (saņēma PID un beidzās).

Cilpas ir ārkārtīgi ērta lieta, rakstot jebkādas programmas vai skriptus, drīzāk pat nepieciešami. Tie ļauj mums izpildīt noteiktu koda sadaļu noteiktu skaitu reižu. Protams, bash ir vairāku veidu cilpas. Mēs aprakstīsim ciklus uz, uz, kamēr, līdz. Lai gan for in un for tiek uzskatīti par viena un tā paša apgalvojuma dažādām sintaksēm, manuprāt, tie atšķiras viens no otra vairāk nekā while no līdz.

Cilpa ar ieejas skaitītāju:

Cikls iekšāŠī ir cilpa ar skaitītāju. Koda bloks, kas atrodas cilpas pamattekstā, tiek atkārtots tik reižu, cik ir vērtības, kas ietvertas operatora for sarakstā, un ar katru atkārtojumu skaitītāja mainīgais (šeit to sauc par var, bet, protams, varat to saukt kā vien vēlaties) ir nākamā saraksta elementa vērtība.
Ja atslēgvārds do atrodas tajā pašā rindā ar vārdu for, tad aiz argumentu saraksta (pirms do) jāievieto semikolu.
Katrs no elementiem<список>var saturēt vairākus argumentus. Tas ir noderīgi, apstrādājot parametru grupas. Šajā gadījumā, lai piespiestu analizēt katru argumentu<списке>, jums ir jāizmanto iestatītā instrukcija
Varat izmantot mainīgo kā sarakstu for cilpā.
IN<списке>For cilpa var izmantot failu nosaukumus, kas savukārt var saturēt aizstājējzīmes. Tas var būt ļoti noderīgi, strādājot ar lielu skaitu failu.
Ja<список>nav norādīts for cilpā, tad kā tas tiek izmantots mainīgais $@ - komandrindas argumentu saraksts.
Veidojot argumentu sarakstu, varat izmantot komandu aizstāšanu for cilpā.
Cilpas izvadi var novirzīt no stdout uz failu vai kaut kur citur (par to varat uzzināt vairāk, apskatot I/O novirzīšanu).

Sintakse:
par var in<список>
darīt
<выполняемые команды>
darīts

Piemērs:
vārdiem vārds1 vārds2 vārds3 vārds4
darīt
echo $names
darīts

Cilpas operators priekš ir vēl viens rakstīšanas veids - ļoti līdzīgs operatora for sintaksei C valodā. Šajā gadījumā, inicializējot skaitītājus, tiek iestatītas mainīgo vai viena mainīgā sākotnējās vērtības un pēc katras cilpas piegājiena nosacījums ir pārbaudīts, ja pārbaude atgriež patiesu, tad sākas nākamā cilpas gājiens. Blokā<приращение счётчиков>mūsu mainīgo skaitītāju vērtībai noteikti ir jāmainās (ne vienmēr uz augšu), lai, pārbaudot nosacījumu, agrāk vai vēlāk mēs iegūtu vērtību false, pretējā gadījumā cilpa nekad nebeigsies. Ļoti ērta un vissvarīgāk pazīstama iespēja, ja kāda darbība ir jāatkārto noteiktu skaitu reižu.

Ar līdzīgu sintaksi:
priekš ((<инициализация счётчиков>; <проверка условия>; <приращение счётчиков>))
darīt
<выполняемые команды>
darīts

Piemērs:
for ((var=1; var<= LIMIT ; var++))
darīt
atbalss $var
darīts

kamēr cilpa:

Šī ir diezgan vienkārša konstrukcija, kas pārbauda stāvokli aiz operatora kamēr un, ja šis nosacījums ir patiess, tas izpilda komandu bloku, kas atrodas starp vārdiem do un done, un pēc tam atkal pāriet pie nosacījuma pārbaudes. Ja pārbaude atgriež false, cikls beidzas un tiek izpildītas šādas komandas: darīts. Tas ir obligāti jānodrošina<проверка условия>atkarīgs no koda, kas darbojas cilpā; pretējā gadījumā, ja pārbaudes rezultāts nemainās, jūs iegūsit bezgalīgu cilpu.
Standarta ievades ierīci kādu laiku var novirzīt uz failu, izmantojot novirzīšanas komandu< в конце цикла.

Sintakse:
kamēr<Проверка условия>
darīt
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
darīts

Piemērs:
kamēr [ $var0 -eq 100 ]
darīt
atbalss $var
var++
darīts

Operators kamēr var būt vairāki nosacījumi. Bet tikai pēdējais no tiem nosaka iespēju turpināt ciklu. Šajā gadījumā cilpas operatora sintakse atšķirsies no parastās.
Sintakse(Es vēlreiz atkārtoju, ka tikai pēdējais nosacījums ietekmē cilpas izpildi) :
kamēr
<условие1>
<условие2>

<условиеN>
darīt
<выполняемые команды - тело цикла>
darīts

Līdz cilpai:

Operators līdz ir ļoti līdzīgs while, tas arī novērtē nosacījumu, bet izpilda cilpas pamattekstu, ja aprēķina rezultāts ir nepatiess. Tas var šķist neparasti, bet līdz tiek novērtēts stāvoklis pirms pirmās cilpas piegājiena, piemēram, while, nevis pēc tās. Tāpat kā for/in cilpām, ievietojot atslēgvārdu do tajā pašā rindā ar cilpas deklarāciju, ir jāievieto rakstzīme ";". pirms darīt.
Tāpat kā iepriekšējā gadījumā, ir svarīgi atcerēties, ka nosacījumam ir jābūt atkarīgam no operācijām cilpas pamattekstā, pretējā gadījumā mūsu skripts nekad netiks pabeigts.

Sintakse:
līdz<Проверка условия>
darīt
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
darīts

Piemērs:
līdz [ $var0 -gt 100] # Nosacījums tiek pārbaudīts iterācijas sākumā.
darīt
atbalss $var
var--
darīts

Laikam ar to pagaidām pietiks. :)

  • Atpakaļ
  • Uz priekšu

Jauni raksti:

  • Tīkla atklāšana neieslēdzas operētājsistēmā Windows 7/8/2008/2012
  • Kļūda: šo lietojumprogrammu neizdevās palaist, jo tā nevarēja atrast vai ielādēt Qt platformas spraudni "windows".
  • Rphost.exe darbinieka procesu automātiskās restartēšanas konfigurēšana 1C 8.3 serverī
  • Kā samazināt darījumu žurnāla (.ldf) lielumu MS SQL 2008/20012

    MS SQL, tāpat kā jebkura pienācīga rūpnieciskā DBVS, kopā ar datu bāzi saglabā darījumu žurnālus, kas ļauj atjaunot stāvokli...

0 Mērans Bala-Kumarans

Es tiešām mēģinu saprast, kāpēc šī while cilpa nekad nebeidzas, kad cilpa sākas, mans LOC mainīgais ir iestatīts uz Testing/, kas ir direktorija, kuru es izveidoju, lai pārbaudītu šo programmu, ir šāds izkārtojums:

Es vēlos, lai cilpa beigtos, tiklīdz visiem direktorijiem ir lietota funkcija "skaitīt".
Lūk, ko es mēģināju;

Es pārbaudīju skaitīšanas funkciju, un tā nerada bezgalīgu cilpu

Es mēģināju manuāli palaist algoritmu

PARSE=1 LOC=$LOC/ count AVAILABLEDIR=$(ls $LOC -AFl | sed "1 d" | grep "/$" | awk "( print $9 )"), savukārt [ $PARSE = "1" ] darīt, ja [[ $(AVAILABLEDIR[@]) == "" ]]; tad PARSE=0 fi DIRBASE=$LOC a in $(AVAILABLEDIR[@]); do LOC="$(DIRBASE)$(a)" LOCLIST="$LOCLIST $LOC" skaits veikts a in $(LOCLIST[@]); do TMPAVAILABLEDIR=$(ls $a -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") PREPEND=$a if [[ $(TMPAVAILABLEDIR[@]) == "" ] ]; pēc tam turpiniet fi uz a in $(TMPAVAILABLEDIR[@]); do TMPAVAILABLEDIR2="$TMPAVAILABLEDIR2 $(PREPEND[@])$(a)" darīts NEWAVAILABLEDIR="$NEWAVAILABLEDIR $TMPAVAILABLEDIR2" done AVAILABLEDIR=$NEWAVAILABLEDIR NEWAVAILABLEDIR="" LOC="" darīts

Es patiešām cīnos, un jebkurš ieguldījums būtu ļoti pateicīgs. Pēdējās divas stundas esmu mēģinājis to izdomāt.

bash infinite-loop

4 atbildes

Jums vajadzētu mēģināt palaist skriptu ar argumentu -x vai ierakstīt to pirmajā rindā:

#!/bin/bash -x

Tad viņš tev pastāsta visu, ko dara.

Šajā gadījumā jūs varat pamanīt divas kļūdas:

    Jūs nekad nepārlādējat TMPAVAILABLEDIR2

    Jūs arī darāt ls parastajos failos.

Ja jums patiešām ir jāizvairās no rekursijas, izmēģiniet šo, pilnīgi bez rekursijas:

#!/bin/bash count() ( atbalss skaitīšana "$1" ) todo=(Pārbaude), kamēr tests $(#todo[@]) != 0 do doit=("$(todo[@])") todo= () for dir in "$(doit[@])" do, lai ievadītu "$dir"/* # ja dir ir tukšs, tas parāda ierakstu ar nosaukumu "*" do test -e "$entry" || turpināt # izlaist ierakstu "*" no tukša dir skaita "$entry" test -d "$entry" || turpināt todo+=("$entry") darīts darīts darīts

Tomēr, lūdzu, pastāstiet man, kāpēc jūs nevarat izmantot rekursiju? Vai tā ir kaut kāda alerģija? Zvērests? Vai jūsu dzīvesvietā ir kādi vietējie likumi pret rekursīvo programmatūru?

Jūs rakstījāt, ka vēlaties veikt "skaitīšanu" visos griezumos. Apskatiet meklēšanas iespējas:

Atrast $LOC -tipa d | kamēr lasīt rež.; do cd $LOC cd $(dir) skaits darīts

vai īsāks (ja jūsu funkciju skaitītājs izmanto direktoriju kā 1. parametru)

Atrast $LOC -tipa d | xargs skaits

Tagad es redzu, ka jūs nevēlaties izmantot find vai ls -R (rekursīvā funkcija). Tad jums vajadzētu izveidot savu rekursīvo funkciju, piemēram,

Funkcija parseDir ( ls -d */ $1 | kamēr lasa direktoriju; saskaitiet parseDir $1/$dir darīts )

Man nav ne jausmas, vai tas darbosies, bet tas ir interesants jautājums, par kuru es nevarēju beigt domāt. Veiksmi

Lai gan taisnība; darīt vārdam "$(echo *)" ; do if [[ -d "$word" ]] ; tad d[$((i++))]="$PWD"/"$word" elif [[ -f "$word" ]] ;tad f[$((j++))]="$PWD"/"$ vārds" fi darīts [[ $k -gt $i ]] && cd .. cd "$d[$((k++))]" || pārtraukums izdarīts