Infinite while loop i et BASH-skript. BASH: beskrivelse av for, while, until-løkker og eksempler på bruk Eksempel: søk etter kjørbare filer


Forfatter: Paul Cobbaut
Publiseringsdato: 16. oktober 2014
Oversettelse: A. Panin
Oversettelsesdato: 21. desember 2014

Kapittel 22. Løkker i skript

test kommando

Testkommandoen lar deg bestemme om et uttrykk er sant eller usant. La oss starte med å teste om heltallsverdien 10 er større enn heltallsverdien 55. $ test 10 -gt 55 ; ekko $? 1$

Testkommandoen returnerer 1 hvis uttrykket er usant. Og, som du vil se i følgende eksempel, vil testkommandoen returnere 0 hvis uttrykket evalueres til sant. $ test 56 -gt 55 ; ekko $? $0

Hvis du er mer komfortabel med å jobbe med strengene sant og usant, kan du bruke testkommandoen som vist nedenfor. $ test 56 -gt 55 && echo true || echo false true $ test 6 -gt 55 && echo true || ekko falsk falsk

Testkommandoen kan også erstattes av hakeparenteser, så kommandoene i eksemplet nedenfor er nøyaktig de samme som kommandoene i eksemplet ovenfor. $ [ 56 -gt 55 ] && echo true || echo false true $ [ 6 -gt 55 ] && echo true || ekko falsk falsk

Nedenfor er eksempler på implementeringer av noen kontroller. Se manntestsiden for oversikt over tilleggsfunksjoner gjennomføring av ulike kontroller. [ -d foo ] Finnes katalog foo? [ -e bar ] Finnes barfilen? [ "/etc" = $PWD ] Er /etc ekvivalent med verdien av $PWD ? [ $1 != "hemmelig" ] Er verdien til den første skriptparameteren forskjellig fra den hemmelige strengen? [ 55 -lt $bar ] Er heltallsverdien 55 mindre enn verdien av $bar ? [ $foo -ge 1000 ] Er verdien av $foo større enn eller lik heltallsverdien 1000 ? ["abc"< $bar ] Будет ли строка abc расположена выше значения переменной $bar в списке после сортировки? [ -f foo ] Является ли foo обычным файлом? [ -r bar ] Является ли bar lesbar fil? [ foo -nt bar ] Er foo nyere enn bar ? [ -o substantivsett ] Er alternativet substantivskall aktivert?

Sjekk operatører kan kombineres med operatører tilsvarende logiske operasjoner"OG" og "ELLER". 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 || ekko usant sant

Betinget hopp om så annet

If then else-konstruksjonen er ment å velge et kodealternativ. Hvis en viss betingelse er sann, vil noe kode bli utført, ellers vil en annen kode bli utført. Eksemplet nedenfor sjekker for eksistensen av en fil, hvoretter, hvis antakelsen om eksistensen av filen bekreftes, vises en tilsvarende melding. #!/bin/bash hvis [ -f isit.txt ] så ekko filen isit.txt eksisterer! else echo file isit.txt ikke funnet! fi

I tilfelle vi sparer denne koden script i en fil som heter "choice", kan det kjøres på samme måte. $ ./choice-filen isit.txt ikke funnet! $ touch isit.txt $ ./choice-filen isit.txt finnes! $

Betinget hopp hvis da elif

Du kan legge ut ny operatør betinget hopp hvis du er inne i en annen blokk ved å bruke elif-operatoren. Nedenfor er et enkelt eksempel på en slik oppføring. #!/bin/bash count=42 hvis [ $count -eq 42 ] så ekko "42 er en gyldig verdi." elif [ $count -gt 42 ] deretter ekko "Too many." annet ekko "Ikke nok." fi

for løkke

Eksemplet nedenfor viser syntaksen til en klassiker for loop i bash-skallet. for i in 1 2 4 do echo $i done

Et eksempel på bruk av en for-løkke kombinert med et inline shell-kall. #!/bin/ksh for teller i `seq 1 20` gjør ekkotelling fra 1 til 20, gjeldende verdi $counter sleep 1 fullført

Et skript helt likt det som er presentert ovenfor, kan opprettes uten å bruke et innebygd kommandoskall ved å bruke bash-skall-deklarasjonen for en rekke verdier (fra verdi..til verdi). #!/bin/bash for teller inn (1..20) gjør ekkotelling fra 1 til 20, gjeldende verdi $counter sleep 1 fullført

Denne for loop bruker en mekanisme for å søke etter filer etter mønster (implementert som en del av kommandoutvidelsesmekanismen). Hvis instruksjonene ovenfor er lagt ut direkte i kommandolinje, vil den fungere på samme måte. kahlan@solexp11$ ls count.ksh go.ksh kahlan@solexp11$ for fil i *.ksh ; gjør cp $file $file.backup ; ferdig kahlan@solexp11$ ls count.ksh count.ksh.backup go.ksh go.ksh.backup

mens loop

Nedenfor er et enkelt eksempel på bruk av en while-løkke. i=100; mens [$i -ge 0]; do echo Nedtelling fra 100 til 0, gjeldende verdi $i; la meg--; ferdig

Uendelige løkker kan implementeres ved å bruke while true eller while:-deklarasjoner, hvor symbolet: er ekvivalent med den manglende operasjonen i Korn-skallet og bash. #!/bin/ksh # endeløs loop mens: do echo hello sleep 1 done

Inntil loop

Nedenfor er et enkelt eksempel på bruk av en inntil-løkke. la i=100; til [$i -le 0]; do echo Nedtelling fra 100 til 1, gjeldende verdi $i; la meg--; ferdig

Praksis: Tester og looper i skript

3. Utvikle et skript som bruker en while-løkke for å telle fra 3 til 7.

4. Utvikle et skript som bruker en til-løkke for å telle ned fra 8 til 4.

5. Utvikle et skript som vil telle filer med en .txt-utvidelse i gjeldende katalog.

6. Bruk if-setningen i det opprettede skriptet for å få det til å fungere riktig hvis det ikke er noen filer med filtypen .txt i gjeldende katalog.

Riktig prosedyre for å fullføre en praktisk oppgave: kontroller og løkker i skript

1. Utvikle et skript som bruker en for-løkke for å telle fra 3 til 7.

#!/bin/bash for i in 3 4 5 6 7 do echo Teller fra 3 til 7, gjeldende verdi $i ferdig

2. Utvikle et skript som bruker en for-løkke for å telle fra 1 til 17000.

Bash-skallet støtter løkker, som lar deg iterere over sekvenser av verdier. Det er det det er grunnleggende struktur slike sykluser:

For var i listen gjør kommandoen utført
I hver iterasjon av løkken vil variabelen var bli skrevet til neste verdi fra liste. Den første passeringen av løkken vil derfor bruke den første verdien fra listen. I den andre - den andre, og så videre - til løkken når det siste elementet.

Itererer over enkle verdier

Det kanskje enkleste eksemplet på en for-løkke i bash-skript er å iterere over en liste med enkle verdier:

#!/bin/bash for var i første andre tredje fjerde femte do echo The $var element ferdig
Resultatene av dette skriptet vises nedenfor. Du kan tydelig se at $var-variabelen inneholder elementer fra listen sekvensielt. Dette skjer til syklusen når den siste av dem.


Enkel for loop

Vær oppmerksom på at $var-variabelen beholder sin verdi når den går ut av loopen, innholdet kan endres, og generelt kan du jobbe med den som alle andre variabler.

Iterering over komplekse verdier

Listen som brukes til å initialisere for-løkken kan inneholde ikke bare enkle strenger som består av ett ord, men også hele fraser som inneholder flere ord og skilletegn. For eksempel kan det se slik ut:

#!/bin/bash for var i første "den andre" "den tredje" "I'll do it" gjør ekko "Dette er: $var" ferdig
Dette er hva som skjer etter at denne loopen har gått gjennom listen. Som du kan se, er resultatet ganske forventet.


Iterering over komplekse verdier
TNW-CUS-FMP - kampanjekode for 10% rabatt på våre tjenester, tilgjengelig for aktivering innen 7 dager"

Initialisere en løkke med en liste hentet fra resultatene av kommandoen

En annen måte å initialisere en for-løkke på er å sende den en liste, som er resultatet av en kommando. Her brukes kommandosubstitusjon for å utføre dem og få resultatene av arbeidet deres.

#!/bin/bash file="myfile" for var in $(cat $file) do echo " $var" done
Dette eksemplet bruker cat-kommandoen, som leser innholdet i en fil. Den resulterende listen over verdier sendes inn i løkken og vises på skjermen. Vær oppmerksom på at filen vi har tilgang til inneholder en liste over ord atskilt med nye linjer; ingen mellomrom brukes.


En løkke som går gjennom innholdet i en fil

Her må vi ta i betraktning at en slik tilnærming, hvis linje-for-linje databehandling forventes, ikke vil fungere for en fil med en mer kompleks struktur, hvis linjene kan inneholde flere ord atskilt med mellomrom. Løkken vil behandle individuelle ord, ikke linjer.

Hva om dette ikke er det du trenger i det hele tatt?

Feltskillere

Grunnen til funksjonen ovenfor er den spesielle miljøvariabel, som kalles IFS (Internal Field Separator) og lar deg spesifisere feltseparatorer. Som standard anser bash-skallet følgende tegn som feltseparatorer:
  • Rom
  • Tab-tegn
  • Linjematingstegn
Hvis bash støter på noen av disse tegnene i dataene, antar den at den blir innledet av den neste uavhengige verdien i listen.

For å løse problemet kan du midlertidig endre IFS-miljøvariabelen. Slik gjør du det i et bash-skript, forutsatt at du bare trenger en ny linje som feltseparator:

IFS=$"\n"
Når du legger til denne kommandoen i bash-skriptet ditt, vil det fungere som forventet, og ignorerer mellomrom og tabulatorer og behandler bare nye linjetegn som feltseparatorer.

#!/bin/bash file="/etc/passwd" IFS=$"\n" for var i $(cat $file) gjør ekko " $var" ferdig
Hvis dette skriptet kjøres, vil det gi ut nøyaktig det som kreves av det, og gi, i hver iterasjon av løkken, tilgang til neste linje skrevet til filen.


Linje for linje kryssing av en fil i en for-løkke

Skilletegn kan også være andre tegn. For eksempel, ovenfor viste vi innholdet i filen /etc/passwd. Brukerdata på linjer er atskilt med kolon. Hvis du trenger å behandle slike strenger i en loop, kan IFS konfigureres slik:

Gjennomgå filer i en katalog

En av de vanligste bruksområdene for loops i bash-skript er å krysse filer som ligger i en katalog og behandle disse filene.

Slik viser du for eksempel filer og mapper:

#!/bin/bash for fil i /home/likegeeks/* gjør hvis [ -d "$file" ] så ekko "$file er en katalog" elif [ -f "$file" ] deretter ekko "$file er en fil" fi ferdig
Hvis du forsto det forrige materialet i denne artikkelserien, bør du forstå strukturen til hvis-da-konstruksjonen, samt hvordan du skiller en fil fra en mappe. Hvis du synes det er vanskelig å forstå koden ovenfor, les dette materialet på nytt.

Dette er hva skriptet vil sende ut.


Viser innholdet i en mappe

Vær oppmerksom på hvordan vi initialiserer loopen, nemlig jokertegn"*" på slutten av mappeadressen. Dette symbolet kan betraktes som et jokertegn som betyr: "alle filer med alle navn." det lar deg organisere automatisk erstatning filnavn som samsvarer med mønsteret.

Når vi tester en betingelse i en if-setning, legger vi variabelnavnet i anførselstegn. Dette gjøres fordi fil- eller mappenavnet kan inneholde mellomrom.

C-stil for løkker

Hvis du er kjent med programmeringsspråket C, kan syntaksen for å beskrive bash for loops virke merkelig for deg, siden du åpenbart er vant til å beskrive loops på denne måten:

For (i = 0; i< 10; i++) { printf("number is %d\n", i); }
I bash-skript kan du bruke for loops, hvis beskrivelse ligner veldig på C-stil looper, selv om det er noen forskjeller. Syklusdiagrammet med denne tilnærmingen ser slik ut:

For ((startverdi av variabel; betingelse for sluttløkke; endring av variabel))
I bash kan det skrives slik:

For ((a = 1; a< 10; a++))
Her er et fungerende eksempel:

#!/bin/bash for ((i=1; i<= 10; i++)) do echo "number is $i" done
Denne koden vil sende ut en liste over tall fra 1 til 10.

Looping i C-stil

mens loop

For-konstruksjonen er ikke den eneste måten å organisere løkker i bash-skript. Du kan også bruke while-løkker her. I en slik sløyfe kan du spesifisere en kommando for å sjekke en bestemt tilstand og utføre hoveddelen av løkken til tilstanden som testes returnerer null, eller et signal for vellykket fullføring av en bestemt operasjon. Når sløyfebetingelsen returnerer en verdi som ikke er null, som betyr en feil, vil sløyfen stoppe.

Her er et diagram over organiseringen av while-løkker
mens tilstandskontrollkommandoen
gjøre
andre lag
ferdig

La oss ta en titt på et eksempelskript med en løkke som dette:

#!/bin/bash var1=5 mens [ $var1 -gt 0 ] gjør ekko $var1 var1=$[ $var1 - 1 ] ferdig
Ved inngangen til loopen sjekkes det om variabelen $var1 er større enn null. I så fall utføres løkkens kropp, der en trekkes fra verdien til variabelen. Dette skjer i hver iterasjon, og vi skriver ut verdien av variabelen til konsollen før den endres. Så snart $var1 når verdien 0, stopper loopen.

Resultat av while-løkken

Hvis du ikke endrer $var1-variabelen, vil dette føre til at skriptet havner i en uendelig løkke.

Nestede løkker

Du kan bruke alle kommandoer i hoveddelen av loopen, inkludert å starte andre looper. Slike konstruksjoner kalles nestede løkker:

#!/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
Nedenfor er hva dette skriptet vil sende ut. Som du kan se, utføres først den første iterasjonen av den ytre løkken, deretter tre iterasjoner av den indre, etter at den er fullført, kommer den ytre løkken i spill igjen, deretter den indre igjen.

Nestede løkker

Behandler filinnhold

Oftest brukes nestede løkker til å behandle filer. Så den ytre løkken itererer over linjene i filen, og den indre jobber allerede med hver linje. Her er for eksempel hvordan behandlingen av /etc/passwd-filen ser ut:

#!/bin/bash IFS=$"\n" for oppføring i $(cat /etc/passwd) do echo "Verdier i $entry –" IFS=: for verdi i $entry do echo " $value" done ferdig
Det er to løkker i dette skriptet. Den første krysser linjene ved å bruke nylinjetegnet som skilletegn. Den interne er opptatt med å analysere strenger hvis felt er atskilt med kolon.

Fildatabehandling

Denne tilnærmingen kan brukes når du behandler CSV-filer, eller lignende filer, ved å skrive skilletegnet inn i IFS-miljøvariabelen etter behov.

Syklusstyring

Kanskje, etter å ha gått inn i løkken, må du stoppe den når løkkevariabelen når en viss verdi som ikke samsvarer med den opprinnelig spesifiserte betingelsen for å avslutte løkken. I en slik situasjon, vil det være nødvendig å vente på normal fullføring av syklusen? Selvfølgelig ikke, og i slike tilfeller vil følgende to kommandoer være nyttige:
  • gå i stykker
  • Fortsette

bryte kommando

Denne kommandoen lar deg avbryte utførelsen av en loop. Den kan brukes til både for og while-løkker:

#!/bin/bash for var1 i 1 2 3 4 5 6 7 8 9 10 gjør hvis [ $var1 -eq 5 ] deretter bryte fi ekko "Number: $var1" ferdig
En slik løkke vil under normale forhold gå gjennom hele listen over verdier fra listen. I vårt tilfelle vil imidlertid utførelsen av den bli avbrutt når $var1-variabelen er lik 5.

Går ut av en for-løkke tidlig

Her er det samme, men for while-løkken:

#!/bin/bash var1=1 mens [ $var1 -lt 10 ] gjør hvis [ $var1 -eq 5 ] deretter bryte fi ekko "Iteration: $var1" var1=$(($var1 + 1)) ferdig
Break-kommandoen, utført når $var1 når 5, bryter løkken. Konsollen vil vise det samme som i forrige eksempel.

fortsett kommandoen

Når denne kommandoen påtreffes i hoveddelen av loopen, slutter den gjeldende iterasjonen tidlig og den neste begynner uten å gå ut av loopen. La oss se på fortsett-kommandoen i en for-løkke:

#!/bin/bash for ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
Når betingelsen inne i løkken er oppfylt, det vil si når $var1 er større enn 5 og mindre enn 10, utfører skallet fortsett-kommandoen. Dette resulterer i å hoppe over de gjenværende kommandoene i løkken og gå videre til neste iterasjon.

Fortsett-kommandoen i en for-løkke

Behandler utdata som kjører i en sløyfe

Datautgang fra en sløyfe kan behandles ved enten å omdirigere utgangen eller sende den til en rørledning. Dette gjøres ved å legge til utdatabehandlingskommandoer etter den ferdige setningen.

For eksempel, i stedet for å vise på skjermen hva som sendes ut i en loop, kan du skrive alt til en fil eller sende det et annet sted:

#!/bin/bash for ((a = 1; a< 10; a++)) do echo "Number is $a" done >myfile.txt ekko "ferdig."
Skallet vil lage filen myfile.txt og omdirigere utdataene fra for-setningen til den filen. La oss åpne filen og sørge for at den inneholder nøyaktig det vi forventer.

Omdiriger loop-utgang til fil

Eksempel: Søk etter kjørbare filer

La oss bruke det vi allerede har dekket og skrive noe nyttig. Hvis du for eksempel trenger å finne ut hvilke kjørbare filer som er tilgjengelige på systemet, kan du skanne alle mappene som er registrert i PATH-miljøvariabelen. Vi har allerede hele arsenalet av verktøy vi trenger for dette, vi trenger bare å sette alt sammen:

#!/bin/bash IFS=: for mappe i $PATH gjør ekko "$folder:" for fil i $folder/* gjør hvis [ -x $fil ] så ekko " $file" fi ferdig gjort
Dette skriptet, lite og enkelt, tillot oss å få en liste over kjørbare filer lagret i mapper fra PATH.

Søker etter kjørbare filer i mapper fra PATH-variabelen

Resultater

I dag snakket vi om for og mens-løkker i bash-skript, hvordan du kjører dem og hvordan du administrerer dem. Nå vet du hvordan du behandler strenger med forskjellige skilletegn i løkker, du vet hvordan du omdirigerer datautgang i løkker til filer, hvordan du viser og analyserer innholdet i kataloger.

Hvis vi antar at du er en utvikler av bash-skript som bare vet om dem det som står i den første delen av denne serien med artikler, og i denne andre, kan du allerede skrive noe nyttig. Foran er den tredje delen, etter å ha forstått hvilken vil du lære hvordan du overfører parametere og kommandolinjebytter til bash-skript, og hva du skal gjøre med det hele.

En kort beskrivelse av forskjellen i løkketyper:

for - vil utføre en handling så lenge det er objekter å utføre (for eksempel lese en strøm fra stdin, en fil eller en funksjon);
mens - utfører handlingen til betingelse er sant;
til - vil bli utført så lenge betingelse vil ikke bli sann, dvs. for nå er det falskt.

FOR Loop

La oss vurdere denne versjonen av skriptet med en loop:

$ cat loop.sh #!/bin/bash for variabel i `ls -1` gjør ekko "$variable" ferdig

Syntaksen er veldig enkel og er ganske tydelig vist i eksemplet:

for (start løkken) variabel (erklær en variabel som vi skal utføre handlinger på) i (send en flyt til løkken) `ls -1` (kommando som skal utføres og sendes til variabelen $variabel). Gjør og gjort er "kroppen" til løkken, innenfor hvilken hovedhandlingene vil bli utført på de mottatte dataene, og ekko "$variabel" er den faktiske handlingen utført av løkken.

La oss nå endre eksemplet litt, og i stedet for å spesifisere kommandoen eksplisitt, bruker vi den andre variabelen:

$ cat loop.sh #!/bin/bash ls=`ls -1` for variabel i $ls do echo "$variable" done

Nå sendes ls -1-kommandoen i en egen variabel, som lar deg jobbe mer fleksibelt med loopen. I stedet for en variabel i en loop, kan du også bruke en funksjon:

$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) for variabel i `lsl` gjør ekko "$variable" utført

Hovedbetingelsen til for-løkken er at den vil bli utført så lenge kommandoen som sendes til den inneholder objekter for handling. Basert på eksemplet ovenfor - så lenge ls -1 har filer å vise - vil loopen sende dem til en variabel og utføre "loop body". Så snart listen over filer i katalogen slutter, vil løkken fullføre kjøringen.

La oss gjøre eksemplet litt mer komplisert.

Katalogen inneholder en liste over filer:

$ ls -1 fil1 fil2 fil3 fil4 fil5 loop.sh nofil1 nofil2 nofil3 nofil4 nofil5

Vi trenger å velge fra dem bare de som ikke har ordet " Nei«:

$ cat loop.sh #!/bin/bash lsl=`ls -1` for variabel i $lsl gjør ekko "$variable" | grep -v "nei" gjort $ ./loop.sh fil1 fil2 fil3 fil4 fil5 loop.sh

Du kan også bruke betingede uttrykk i en loop ( betingede uttrykk) […] for å sjekke forholdene og break-setningen for å avbryte sløyfen hvis tilstanden utløses.

Tenk på dette eksemplet:

$ cat loop.sh #!/bin/bash lsl=`ls -1` for variabel i $lsl gjør hvis [ $variable != "loop.sh" ] så ekko "$variable" | grep -v "nei" ellers bryte fi ferdig

Sløyfen vil fortsette til filen loop.sh blir oppdaget. Så snart utførelsen av loopen når denne filen, vil loopen bli avbrutt av break-kommandoen:

$ ./loop.sh fil1 fil2 fil3 fil4 fil5

Et annet eksempel er bruken av aritmetiske operasjoner rett før løkken utføres:

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

Her setter vi tre kontrollkommandoer - count=1, en kontrollerende betingelse - mens antallet er mindre enn 11, og en kommando som skal utføres - count +1:

WHILE og TILL løkker

Et enkelt eksempel som tydelig viser hvordan while-løkken fungerer:

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

Vi setter $count-variabelen til null, og kjører deretter whi le-løkken med betingelsen "mens $count er mindre enn ti, utfør loopen." I sløyfens kropp utfører vi postfix-økning+1 til $count-variabelen og resultatet skrives ut til stdout.

Utførelsesresultat:

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

Så snart verdien av $count-variabelen ble 10, stoppet loopen.

Et godt eksempel på en "uendelig" loop som viser hvordan mens fungerer:

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

Inntil-løkken fungerer på samme måte, men i motsatt retning:

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

Her setter vi en lignende betingelse, men i stedet for "mens variabelen er mindre enn 10", spesifiserer vi "til variabelen blir større enn 10." Utførelsesresultat:

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

Hvis eksemplet ovenfor på en "endeløs sløyfe" utføres ved å bruke til, vil den ikke sende ut noe, i motsetning til mens:

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

Fordi " betingelse"opprinnelig" ekte"—brødteksten til løkken vil ikke bli utført.

Akkurat som i for-løkken kan du bruke funksjoner i mens og til. For eksempel en sløyfe fra et virkelighetsskript som sjekker serverstatusen Tomcat(PID er hentet fra systemet SLES, kan avvike i andre systemer), en litt forenklet versjon:

$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(skriv ut $2)"` ) mens check_tomcat_status gjør hvis [ -n "$ RUN" ] deretter printf "ADVARSEL: Tomcat kjører fortsatt med PID $RUN." else printf "Tomcat stoppet, fortsetter...nn" break fi ferdig

Utførelsesresultat:

$ ./loop.sh ADVARSEL: Tomcat kjører fortsatt med PID 14435 26548. ADVARSEL: Tomcat kjører fortsatt med PID 14435 26548. ADVARSEL: Tomcat kjører fortsatt med PID 14435 26548. ADVARSEL: Tomcat kjører fortsatt med PID 1654438 Tomcat fortsatt. kjører med PID 14435 26548. ADVARSEL: Tomcat kjører fortsatt med PID 14435 26548. ADVARSEL: Tomcat kjører fortsatt med PID 14435 26548. ADVARSEL: Tomcat kjører fortsatt med PID 14435

Full versjon:

Check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) mens check_tomcat_status; gjør hvis [ -n "$RUN" ] så printf "ADVARSEL: Tomcat kjører fortsatt med PID $RUN. Stopp det? " svar "Stopper Tomcat..." "Forsetter installasjonen..." && $CATALINA_HOME/bin/shutdown sh 2&>1 /dev/null || break sleep 2 if [ -n "$RUN" ] then printf "Tomcat kjører fortsatt. Kill it?" svar "Killing Tomcat..." "Forsetter installasjon...n" && kill $RUN || pause sleep 2 fi annet printf "Tomcat stoppet, fortsetter...nn" pause fi ferdig

Svarfunksjonen ble beskrevet i artikkelen, men her brukes en litt forbedret versjon:

Svar () ( mens du leser svar; gjør ekko-case $respons i |) printf "$1n" returner 0 pause ;; |) printf "$2n" returner 1 pause ;; *) printf "Vennligst, skriv inn Y(yes) eller N(no)! " esac done )

Her var det mulig å bruke både mens og til - men ikke en for-løkke, siden for ville ha fungert en gang (mottatt PID og avsluttet).

Loops er en ekstremt praktisk ting når du skriver programmer eller skript, snarere nødvendig. De lar oss utføre en bestemt del av koden et spesifisert antall ganger. Naturligvis har bash flere typer løkker. Vi vil beskrive syklusene for i, for, mens, inntil. Selv om for in og for regnes som forskjellige syntakser av samme utsagn, skiller de seg etter min mening fra hverandre mer enn mens fra til.

Løkke med teller for inn:

Syklus for i Dette er en løkke med en teller. Kodeblokken som ligger i løkkens kropp gjentas så mange ganger som det er verdier i listen over for in-operatoren, og med hver repetisjon tellervariabelen (her kalles den var, men selvfølgelig du kan kalle det hva du vil) har verdien av det neste elementet på listen.
Hvis nøkkelordet do er på samme linje som ordet for, må du sette et semikolon etter listen over argumenter (før du gjør det).
Hvert av elementene<список>kan inneholde flere argumenter. Dette er nyttig når du behandler grupper av parametere. I dette tilfellet, for å tvinge parsing av hvert av argumentene i<списке>, må du bruke den angitte instruksjonen
Du kan bruke en variabel som en liste i en for-løkke.
I<списке>For-løkken kan bruke filnavn, som igjen kan inneholde jokertegn. Dette kan være svært nyttig når du arbeider med et stort antall filer.
Hvis<список>ikke er spesifisert i for-løkken, så brukes variabelen $@ som den - en liste over kommandolinjeargumenter.
Når du oppretter en liste med argumenter, kan du bruke kommandoerstatning i en for-løkke.
Utgangen fra løkken kan omdirigeres fra stdout til en fil eller et annet sted (du kan lære mer om dette ved å se på I/O-omdirigering).

Syntaks:
for var in<список>
gjøre
<выполняемые команды>
ferdig

Eksempel:
for navn i navn1 navn2 navn3 navn4
gjøre
ekko $navn
ferdig

Sløyfeoperatør til har en annen måte å skrive på - veldig lik syntaksen til for-operatoren i C-språket. I dette tilfellet, når tellerne initialiseres, settes startverdiene til variabler eller én variabel, og etter hvert pass av løkken blir betingelsen er merket, hvis sjekken returnerer sann, begynner neste pass i løkken. I blokken<приращение счётчиков>verdien av våre variable tellere må nødvendigvis endres (ikke nødvendigvis oppover) slik at når vi sjekker betingelsen, før eller siden får vi verdien false, ellers vil løkken aldri ta slutt. Et veldig praktisk og viktigst kjent alternativ hvis en operasjon må gjentas et spesifisert antall ganger.

Med en lignende syntaks:
for ((<инициализация счётчиков>; <проверка условия>; <приращение счётчиков>))
gjøre
<выполняемые команды>
ferdig

Eksempel:
for ((var=1; var<= LIMIT ; var++))
gjøre
ekko $var
ferdig

mens loop:

Dette er en ganske enkel konstruksjon som sjekker tilstanden bak operatøren samtidig som og hvis denne betingelsen er sann, utfører den blokken med kommandoer som ligger mellom ordene gjør og ferdig, og fortsetter så igjen til å kontrollere tilstanden. Hvis sjekken returnerer falsk, avsluttes syklusen og følgende kommandoer begynner å bli utført: ferdig. Det er viktig å sikre det<проверка условия>avhengig av koden som kjører i løkken; ellers, hvis resultatet av kontrollen ikke endres, vil du få en uendelig løkke.
Standardinndataenheten for en while-løkke kan omdirigeres til en fil ved hjelp av omdirigeringskommandoen< в конце цикла.

Syntaks:
samtidig som<Проверка условия>
gjøre
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
ferdig

Eksempel:
mens [ $var0 -eq 100 ]
gjøre
ekko $var
var++
ferdig

Operatør samtidig som kan ha flere forhold. Men bare den siste av dem bestemmer muligheten for å fortsette syklusen. I dette tilfellet vil syntaksen til løkkeoperatøren være forskjellig fra den vanlige.
Syntaks(Jeg gjentar nok en gang at bare den siste betingelsen påvirker utførelsen av loopen) :
samtidig som
<условие1>
<условие2>

<условиеN>
gjøre
<выполняемые команды - тело цикла>
ferdig

Inntil loop:

Operatør før er veldig lik while, evaluerer den også betingelsen, men utfører selve løkken hvis resultatet av beregningen er usant. Det kan virke uvanlig, men til evaluerer tilstanden før den første passeringen av løkken, som mens, og ikke etter den. Som med for/in-løkker, når du plasserer nøkkelordet do på samme linje som loop-deklarasjonen, må du sette inn et ";"-tegn. før gjør.
Som i forrige tilfelle, er det viktig å huske at tilstanden må avhenge av operasjonene i loop-kroppen, ellers vil skriptet vårt aldri fullføres.

Syntaks:
før<Проверка условия>
gjøre
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
ferdig

Eksempel:
til [ $var0 -gt 100] # Betingelsen sjekkes i begynnelsen av iterasjonen.
gjøre
ekko $var
var--
ferdig

Det er nok nok foreløpig. :)

  • Tilbake
  • Framover

Nye artikler:

  • Nettverksoppdaging slås ikke på i Windows 7/8/2008/2012
  • Feil: Denne applikasjonen kunne ikke starte fordi den ikke kunne finne eller laste Qt-plattformplugin "windows".
  • Konfigurerer automatisk omstart av rphost.exe-arbeidsprosesser på 1C 8.3-serveren
  • Hvordan redusere størrelsen på transaksjonsloggen (.ldf) i MS SQL 2008/20012

    MS SQL, som enhver anstendig industriell DBMS, sammen med databasen, holder transaksjonslogger som lar deg rulle tilbake tilstanden ...

0 Meeran Bala-Kumaran

Jeg prøver virkelig å forstå hvorfor dette mens loop aldri slutter, når loopen starter er LOC-variabelen min satt til Testing/ som er katalogen jeg opprettet for å teste dette programmet har følgende layout:

Jeg vil at løkken skal avsluttes når alle kataloger har fått "telling"-funksjonen brukt.
Her er hva jeg prøvde;

Jeg sjekket tellefunksjonen, og den lager ikke en uendelig løkke

Jeg prøvde å kjøre algoritmen manuelt

PARSE=1 LOC=$LOC/ count AVAILABLEDIR=$(ls $LOC -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") mens [ $PARSE = "1" ] gjør hvis [[ $(AVAILABLEDIR[@]) == "" ]]; så PARSE=0 fi DIRBASE=$LOC for a i $(AVAILABLEDIR[@]); do LOC="$(DIRBASE)$(a)" LOCLIST="$LOCLIST $LOC" telling utført for en i $(LOCLIST[@]); gjør TMPAVAILABLEDIR=$(ls $a -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") PREPEND=$a hvis [[ $(TMPAVAILABLEDIR[@]) == "" ] ]; fortsett deretter fi for a i $(TMPAVAILABLEDIR[@]); do TMPAVAILABLEDIR2="$TMPAVAILABLEDIR2 $(PREPEND[@])$(a)" ferdig NEWAVAILABLEDIR="$NEWAVAILABLEDIR $TMPAVAILABLEDIR2" ferdig AVAILABLEDIR=$NEWAVAILABLEDIR NEWAVAILABLEDIR="" LOC="" ferdig

Jeg sliter virkelig og alle innspill ville bli satt stor pris på, jeg har prøvd å finne ut av dette de siste to timene.

bash infinite-loop

4 svar

Du bør prøve å kjøre skriptet med -x-argumentet eller skrive det på den første linjen:

#!/bin/bash -x

Så forteller han deg alt han gjør.

I dette tilfellet kan du legge merke til to feil:

    Du laster aldri inn TMPAVAILABLEDIR2 på nytt

    Du gjør også ls på vanlige filer.

Hvis du virkelig må unngå rekursjon, prøv dette, helt uten rekursjon:

#!/bin/bash count() ( ekkotelling "$1" ) todo=(Testing) mens test $(#todo[@]) != 0 do doit=("$(todo[@])") todo= () for dir i "$(doit[@])" gjør for oppføring i "$dir"/* # hvis dir er tom, viser dette en oppføring som heter "*" do test -e "$entry" || fortsett # hopp over oppføringen "*" i en tom dir count "$entry" test -d "$entry" || fortsett todo+=("$entry") ferdig gjort ferdig

Men fortell meg hvorfor du ikke kan bruke rekursjon? Er dette en slags allergi? Løfte? Er det noen lokale lover mot rekursiv programvare der du bor?

Du skrev at du ønsker å utføre en "telling" på alle kutt. Sjekk ut søkealternativene:

Finn $LOC -type d | mens du leser dir; gjør cd $LOC cd $(dir) teller ferdig

eller kortere (når funksjonstelleren din tar katalog som parameter 1)

Finn $LOC -type d | xargs teller

Nå ser jeg at du ikke vil bruke find eller ls -R (rekursiv funksjon). Da bør du lage din egen rekursive funksjon som

Funksjon parseDir ( ls -d */ $1 | mens du leser dir; tell parseDir $1/$dir ferdig)

Jeg aner ikke om dette vil fungere, men det er et interessant spørsmål som jeg ikke kunne slutte å tenke på. Lykke til

Mens sant ; gjør for ord i "$(ekko *)" ; gjør hvis [[ -d "$ord" ]] ; deretter d[$((i++))]="$PWD"/"$word" elif [[ -f "$word" ]] ;så f[$((j++))]="$PWD"/"$ word" fi ferdig [[ $k -gt $i ]] && cd .. cd "$d[$((k++))]" || pause gjort