Pse cikli for nuk funksionon në një direktori. Pse cikli for nuk ekzekutohet në direktorinë Loops në skriptet bash

Shtëpi / Nuk ndizet

Kujdes: Ka përfitime të fshehura në postim!

për sythe

Predha bash mbështet sythe, të cilat ju lejojnë të përsërisni mbi sekuenca vlerash. Këtu është struktura themelore e sytheve të tilla:

Për var në listë do të kryeni komandën

Në çdo përsëritje të ciklit, vlera e radhës nga lista do të shkruhet në variablin var. Prandaj, kalimi i parë i ciklit do të përdorë vlerën e parë nga lista. Në të dytën - e dyta, e kështu me radhë - derisa laku të arrijë elementin e fundit.

Përsëritja mbi vlera të thjeshta

Ndoshta shembulli më i thjeshtë i një cikli for në skriptet bash është përsëritja mbi një listë vlerash të thjeshta:

#!/bin/bash për var në të dytën e parë të tretën e katërt të pestën bëj echo Artikulli $var u krye

Rezultatet e këtij skenari janë paraqitur më poshtë. Mund të shihni qartë se ndryshorja $var përmban elemente nga lista në mënyrë sekuenciale. Kjo ndodh derisa cikli të arrijë në të fundit prej tyre.



Thjeshtë për lak

Ju lutemi vini re se ndryshorja $var ruan vlerën e saj kur del nga cikli, përmbajtja e saj mund të ndryshohet dhe në përgjithësi, ju mund të punoni me të si çdo variabël tjetër.

Përsëritja mbi vlerat komplekse

Lista e përdorur për të inicializuar ciklin for mund të përmbajë jo vetëm vargje të thjeshta të përbëra nga një fjalë, por edhe fraza të tëra që përmbajnë disa fjalë dhe shenja pikësimi. Për shembull, mund të duket kështu:

#!/bin/bash për var në të parën "e dyta" "e treta" "Unë do ta bëj" bëj echo "Kjo është: $var" e kryer

Kjo është ajo që ndodh pasi ky lak kalon nëpër listë. Siç mund ta shihni, rezultati është mjaft i pritshëm.



Përsëritja mbi vlerat komplekse
TNW-CUS-FMP - kod promocional për një zbritje prej 10% në shërbimet tona, i disponueshëm për aktivizim brenda 7 ditëve"

Inicializimi i një cikli me një listë të marrë nga rezultatet e komandës

Një mënyrë tjetër për të inicializuar një cikli for është t'i kaloni një listë, e cila është rezultat i një komande. Këtu zëvendësimi i komandës përdoret për t'i ekzekutuar ato dhe për të marrë rezultatet e punës së tyre.

#!/bin/bash file="myfile" për var në $(cat $file) bëj echo " $var" u krye

Ky shembull përdor komandën cat, e cila lexon përmbajtjen e një skedari. Lista rezultuese e vlerave kalon në lak dhe shfaqet në ekran. Ju lutemi vini re se skedari që ne po aksesojmë përmban një listë fjalësh të ndara me rreshta të rinj;



Një lak që kalon nëpër përmbajtjen e një skedari

Këtu duhet të kemi parasysh se një qasje e tillë, nëse pritet përpunimi i të dhënave rresht pas rreshti, nuk do të funksionojë për një skedar me strukturë më komplekse, rreshtat e të cilit mund të përmbajnë disa fjalë të ndara me hapësira. Cikli do të përpunojë fjalë individuale, jo rreshta.

Po sikur kjo nuk është ajo që ju nevojitet fare?

Ndarësit e fushës

Arsyeja e veçorisë së mësipërme është e veçanta variabli i mjedisit, i cili quhet IFS (Internal Field Separator) dhe ju lejon të specifikoni ndarësit e fushave. Si parazgjedhje, guaska bash i konsideron karakteret e mëposhtme si ndarës të fushave:

  • Hapësirë
  • Karakteri i skedës
  • Karakteri i furnizimit të linjës

Nëse bash ndeshet me ndonjë nga këto karaktere në të dhëna, supozon se paraprihet nga vlera tjetër e pavarur në listë.

Për të zgjidhur problemin, mund të ndryshoni përkohësisht variablin e mjedisit IFS. Ja se si ta bëni atë në një skript bash, duke supozuar se ju nevojitet vetëm një rresht i ri si ndarës i fushës:

IFS=$"n"

Pasi ta shtoni këtë komandë në skriptin tuaj bash, ai do të funksionojë siç pritej, duke injoruar hapësirat dhe skedat dhe duke trajtuar vetëm karakteret e linjës së re si ndarës fushash.

#!/bin/bash file="/etc/passwd" IFS=$"n" për var në $(cat $file) bëj jehonë " $var" u krye

Nëse ky skript ekzekutohet, ai do të nxjerrë saktësisht atë që kërkohet prej tij, duke i dhënë, në çdo përsëritje të ciklit, akses në rreshtin tjetër të shkruar në skedar.



Kalimi rresht pas rreshti i një skedari në një cikli for

Ndarësit mund të jenë edhe personazhe të tjerë. Për shembull, më lart kemi shfaqur përmbajtjen e skedarit /etc/passwd. Të dhënat e përdoruesit në rreshta ndahen me dy pika. Nëse keni nevojë të përpunoni vargje të tilla në një lak, IFS mund të konfigurohet si kjo:

Kalimi i skedarëve të përfshirë në një direktori

Një nga përdorimet më të zakonshme të sytheve for në skriptet bash është kalimi i skedarëve të vendosur në një direktori dhe përpunimi i atyre skedarëve.

Për shembull, ja se si të listoni skedarët dhe dosjet:

#!/bin/bash për skedarin në /home/likegeeks/* bëni nëse [ -d "$file" ] atëherë bëni jehonë "$file është një drejtori" elif [ -f "$file" ] pastaj echo "$file është një dosje" fi bërë

Predha bash mbështet sythe, të cilat ju lejojnë të përsërisni mbi sekuenca vlerash. Këtu është struktura themelore e sytheve të tilla:

Për var në listë do të kryeni komandën
Në çdo përsëritje të ciklit, vlera e radhës nga lista do të shkruhet në variablin var. Prandaj, kalimi i parë i ciklit do të përdorë vlerën e parë nga lista. Në të dytën - e dyta, e kështu me radhë - derisa laku të arrijë elementin e fundit.

Përsëritja mbi vlera të thjeshta

Ndoshta shembulli më i thjeshtë i një cikli for në skriptet bash është përsëritja mbi një listë vlerash të thjeshta:

#!/bin/bash për var në të dytën e parë të tretën e katërt të pestën bëj echo Artikulli $var u krye
Rezultatet e këtij skenari janë paraqitur më poshtë. Mund të shihni qartë se ndryshorja $var përmban elemente nga lista në mënyrë sekuenciale. Kjo ndodh derisa cikli të arrijë në të fundit prej tyre.


Thjeshtë për lak

Ju lutemi vini re se ndryshorja $var ruan vlerën e saj kur del nga cikli, përmbajtja e saj mund të ndryshohet dhe në përgjithësi, ju mund të punoni me të si çdo variabël tjetër.

Përsëritja mbi vlerat komplekse

Lista e përdorur për të inicializuar ciklin for mund të përmbajë jo vetëm vargje të thjeshta të përbëra nga një fjalë, por edhe fraza të tëra që përmbajnë disa fjalë dhe shenja pikësimi. Për shembull, mund të duket kështu:

#!/bin/bash për var në të parën "e dyta" "e treta" "Unë do ta bëj" bëj echo "Kjo është: $var" e kryer
Kjo është ajo që ndodh pasi ky lak kalon nëpër listë. Siç mund ta shihni, rezultati është mjaft i pritshëm.


Përsëritja mbi vlerat komplekse
TNW-CUS-FMP - kod promocional për një zbritje prej 10% në shërbimet tona, i disponueshëm për aktivizim brenda 7 ditëve"

Inicializimi i një cikli me një listë të marrë nga rezultatet e komandës

Një mënyrë tjetër për të inicializuar një cikli for është t'i kaloni një listë, e cila është rezultat i një komande. Këtu zëvendësimi i komandës përdoret për t'i ekzekutuar ato dhe për të marrë rezultatet e punës së tyre.

#!/bin/bash file="myfile" për var në $(cat $file) bëj echo " $var" u krye
Ky shembull përdor komandën cat, e cila lexon përmbajtjen e një skedari. Lista rezultuese e vlerave kalon në lak dhe shfaqet në ekran. Ju lutemi vini re se skedari që ne po aksesojmë përmban një listë fjalësh të ndara me rreshta të rinj;


Një lak që kalon nëpër përmbajtjen e një skedari

Këtu duhet të kemi parasysh se një qasje e tillë, nëse pritet përpunimi i të dhënave rresht pas rreshti, nuk do të funksionojë për një skedar me strukturë më komplekse, rreshtat e të cilit mund të përmbajnë disa fjalë të ndara me hapësira. Cikli do të përpunojë fjalë individuale, jo rreshta.

Po sikur kjo nuk është ajo që ju nevojitet fare?

Ndarësit e fushës

Arsyeja për veçorinë e mësipërme është një variabël i veçantë mjedisor i quajtur IFS (Ndarës i brendshëm i fushës) që ju lejon të specifikoni ndarësit e fushave. Si parazgjedhje, guaska bash i konsideron karakteret e mëposhtme si ndarës të fushave:
  • Hapësirë
  • Karakteri i skedës
  • Karakteri i furnizimit të linjës
Nëse bash ndeshet me ndonjë nga këto karaktere në të dhëna, ai supozon se paraprihet nga vlera tjetër e pavarur në listë.

Për të zgjidhur problemin, mund të ndryshoni përkohësisht variablin e mjedisit IFS. Ja se si ta bëni atë në një skript bash, duke supozuar se ju nevojitet vetëm një rresht i ri si ndarës i fushës:

IFS=$"\n"
Pasi ta shtoni këtë komandë në skriptin tuaj bash, ai do të funksionojë siç pritej, duke injoruar hapësirat dhe skedat dhe duke trajtuar vetëm karakteret e linjës së re si ndarës fushash.

#!/bin/bash file="/etc/passwd" IFS=$"\n" për var në $(cat $file) bëj jehonë " $var" u krye
Nëse ky skript ekzekutohet, ai do të nxjerrë saktësisht atë që kërkohet prej tij, duke i dhënë, në çdo përsëritje të ciklit, akses në rreshtin tjetër të shkruar në skedar.


Kalimi rresht pas rreshti i një skedari në një cikli for

Ndarësit mund të jenë edhe personazhe të tjerë. Për shembull, më lart kemi shfaqur përmbajtjen e skedarit /etc/passwd. Të dhënat e përdoruesit në rreshta ndahen me dy pika. Nëse keni nevojë të përpunoni vargje të tilla në një lak, IFS mund të konfigurohet si kjo:

Kalimi i skedarëve të përfshirë në një direktori

Një nga përdorimet më të zakonshme të sytheve for në skriptet bash është kalimi i skedarëve të vendosur në një direktori dhe përpunimi i atyre skedarëve.

Për shembull, ja se si të listoni skedarët dhe dosjet:

#!/bin/bash për skedarin në /home/likegeeks/* bëni nëse [ -d "$file" ] atëherë bëni jehonë "$file është një drejtori" elif [ -f "$file" ] pastaj echo "$file është një skedar" fi mbaruar
Nëse e keni kaluar këtë seri artikujsh, duhet të kuptoni strukturën e konstruksionit nëse-atëherë, si dhe si të dalloni një skedar nga një dosje. Nëse e keni të vështirë të kuptoni kodin e mësipërm, rilexoni këtë material.

Kjo është ajo që do të dalë skripti.


Shfaqja e përmbajtjes së një dosjeje

Vini re se si ne inicializojmë ciklin, përkatësisht karakterin "*" në fund të adresës së dosjes. Ky simbol mund të mendohet si një shkronja e egër që do të thotë: "të gjithë skedarët me çdo emër". ju lejon të organizoni zëvendësimin automatik të emrave të skedarëve që përputhen me modelin.

Kur testojmë një kusht në një deklaratë if, ne e mbyllim emrin e ndryshores në thonjëza. Kjo është bërë sepse emri i skedarit ose dosjes mund të përmbajë hapësira.

C-style për sythe

Nëse jeni njohur me gjuhën e programimit C, sintaksa për përshkrimin e bash për sythe mund t'ju duket e çuditshme, pasi padyshim jeni mësuar të përshkruani sythe në këtë mënyrë:

Për (i = 0; i< 10; i++) { printf("number is %d\n", i); }
Në skriptet bash mund të përdorni për sythe, përshkrimi i të cilave duket shumë i ngjashëm me sythe të stilit C, megjithëse ka disa dallime. Diagrami i ciklit me këtë qasje duket si ky:

Për ((vlera fillestare e ndryshores; kushti për përfundimin e ciklit; ndryshimi i ndryshores))
Në bash mund të shkruhet kështu:

Për ((a = 1; a< 10; a++))
Këtu është një shembull pune:

#!/bin/bash për ((i=1; i<= 10; i++)) do echo "number is $i" done
Ky kod do të nxjerrë një listë me numra nga 1 deri në 10.

Drejtimi i një lak në stilin C

ndërsa lak

Konstrukti for nuk është mënyra e vetme për të organizuar sythe në skriptet bash. Ju gjithashtu mund të përdorni ndërsa loops këtu. Në një lak të tillë, ju mund të specifikoni një komandë për të kontrolluar një gjendje të caktuar dhe për të ekzekutuar trupin e ciklit derisa kushti që testohet të kthehet zero, ose një sinjal për përfundimin me sukses të një operacioni të caktuar. Kur kushti i ciklit kthen një vlerë jo zero, që do të thotë një gabim, cikli do të ndalojë.

Këtu është një diagram i organizimit të sytheve while
ndërsa komanda e kontrollit të gjendjes
bëj
ekipet e tjera
bërë

Le të hedhim një vështrim në një shembull skripti me një lak si ky:

#!/bin/bash var1=5 ndërsa [ $var1 -gt 0 ] bëj echo $var1 var1=$[ $var1 - 1 ] e kryer
Në hyrje të ciklit, kontrollohet nëse ndryshorja $var1 është më e madhe se zero. Nëse po, ekzekutohet trupi i ciklit, në të cilin njëra zbritet nga vlera e ndryshores. Kjo ndodh në çdo përsëritje, dhe ne shtypim vlerën e ndryshores në tastierë përpara se të modifikohet. Sapo $var1 arrin vlerën 0, cikli ndalon.

Rezultati i ciklit while

Nëse nuk e modifikoni variablin $var1, kjo do të bëjë që skripti të përfundojë në një lak të pafund.

Unazat e mbivendosura

Ju mund të përdorni çdo komandë në trupin e ciklit, duke përfshirë nisjen e sytheve të tjera. Ndërtime të tilla quhen sythe të mbivendosur:

#!/bin/bash për ((a = 1; a<= 3; a++)) do echo "Start $a:" for ((b = 1; b <= 3; b++)) do echo " Inner loop: $b" done done
Më poshtë është ajo që ky skenar do të dalë. Siç mund ta shihni, fillimisht ekzekutohet përsëritja e parë e lakut të jashtëm, më pas tre përsëritje të atij të brendshëm, pas përfundimit të tij përsëri hyn në lojë laku i jashtëm, pastaj përsëri ai i brendshëm.

Unazat e mbivendosura

Përpunimi i përmbajtjes së skedarit

Më shpesh, sythe të mbivendosur përdoren për të përpunuar skedarët. Pra, laku i jashtëm po përsëritet mbi linjat e skedarit, dhe ai i brendshëm tashmë po punon me secilën rresht. Këtu, për shembull, është se si duket përpunimi i skedarit /etc/passwd:

#!/bin/bash IFS=$"\n" për hyrje në $(cat /etc/passwd) bëni jehonë "Vlerat në $entry –" IFS=: për vlerën në $entry bëni echo " $value" u krye bërë
Ka dy sythe në këtë skenar. I pari përshkon linjat duke përdorur karakterin e linjës së re si ndarës. E brendshme është e zënë me analizimin e vargjeve, fushat e të cilave janë të ndara me dy pika.

Përpunimi i të dhënave të skedarit

Kjo qasje mund të përdoret gjatë përpunimit të skedarëve CSV, ose ndonjë skedari të ngjashëm, duke shkruar karakterin ndarës në variablin e mjedisit IFS sipas nevojës.

Menaxhimi i ciklit

Ndoshta, pasi të keni hyrë në lak, do t'ju duhet ta ndaloni atë kur ndryshorja e ciklit të arrijë një vlerë të caktuar që nuk korrespondon me kushtin e specifikuar fillimisht për përfundimin e ciklit. Në një situatë të tillë, a do të jetë e nevojshme të prisni përfundimin normal të ciklit? Sigurisht që jo, dhe në raste të tilla dy komandat e mëposhtme do të jenë të dobishme:
  • thyej
  • vazhdojnë

komanda e thyerjes

Kjo komandë ju lejon të ndërprisni ekzekutimin e një cikli. Mund të përdoret si për sythe for dhe while:

#!/bin/bash për var1 në 1 2 3 4 5 6 7 8 9 10 bëni nëse [ $var1 -eq 5 ] atëherë thyeni jehonën fi "Numri: $var1" u krye
Një lak i tillë, në kushte normale, do të kalojë në të gjithë listën e vlerave nga lista. Sidoqoftë, në rastin tonë, ekzekutimi i tij do të ndërpritet kur ndryshorja $var1 është e barabartë me 5.

Dalja nga një lak për herët

Këtu është e njëjta gjë, por për ciklin while:

#!/bin/bash var1=1 ndërsa [ $var1 -lt 10 ] bëj nëse [ $var1 -eq 5 ] pastaj thyej fi jehonë "Përsëritja: $var1" var1=$(($var1 + 1)) u krye
Komanda break, e ekzekutuar kur $var1 arrin 5, thyen ciklin. Konsola do të shfaq të njëjtën gjë si në shembullin e mëparshëm.

vazhdoni komandën

Kur kjo komandë haset në trupin e ciklit, përsëritja aktuale përfundon herët dhe fillon tjetra, pa dalë nga cikli. Le të shohim komandën vazhdim në një cikli for:

#!/bin/bash për ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
Kur kushti brenda lakut plotësohet, domethënë kur $var1 është më i madh se 5 dhe më i vogël se 10, shell-i ekzekuton komandën vazhdim. Kjo rezulton në kapërcimin e komandave të mbetura në trupin e ciklit dhe kalimin në përsëritjen tjetër.

Komanda e vazhdimit në një cikli for

Përpunimi i prodhimit që ekzekutohet në një lak

Dalja e të dhënave nga një lak mund të përpunohet ose duke e ridrejtuar daljen ose duke e kaluar atë në një tubacion. Kjo bëhet duke shtuar komandat e përpunimit të daljes pas deklaratës së bërë.

Për shembull, në vend që të shfaqni në ekran atë që del në një lak, mund t'i shkruani të gjitha në një skedar ose ta kaloni diku tjetër:

#!/bin/bash për ((a = 1; a< 10; a++)) do echo "Number is $a" done >myfile.txt jehonë "përfundoi".
Predha do të krijojë skedarin myfile.txt dhe do të ridrejtojë daljen e deklaratës for në atë skedar. Le të hapim skedarin dhe të sigurohemi që ai të përmbajë saktësisht atë që presim.

Ridrejtoni daljen e ciklit në skedar

Shembull: Kërkoni për skedarë të ekzekutueshëm

Le të përdorim atë që kemi mbuluar tashmë dhe të shkruajmë diçka të dobishme. Për shembull, nëse duhet të zbuloni se cilët skedarë të ekzekutueshëm janë të disponueshëm në sistem, mund të skanoni të gjitha dosjet e regjistruara në variablin e mjedisit PATH. Ne tashmë kemi të gjithë arsenalin e mjeteve që na duhen për këtë, thjesht duhet t'i bashkojmë të gjitha:

#!/bin/bash IFS=: për dosjen në $PATH bëj jehonë "$folder:" për skedarin në $folder/* bëj nëse [ -x $file ] pastaj eko " $file" për të përfunduar
Një skenar i tillë, i vogël dhe i pakomplikuar, na lejoi të merrnim një listë të skedarëve të ekzekutueshëm të ruajtur në dosje nga PATH.

Kërkimi i skedarëve të ekzekutueshëm në dosje nga ndryshorja PATH

Rezultatet

Sot folëm për sythe for dhe while në skriptet bash, si t'i ekzekutojmë ato dhe si t'i menaxhojmë ato. Tani ju e dini se si të përpunoni vargjet me kufizues të ndryshëm në sythe, ju dini si të ridrejtoni daljen e të dhënave në sythe në skedarë, si të shikoni dhe analizoni përmbajtjen e drejtorive.

Nëse supozojmë se jeni një zhvillues i skripteve bash që di për to vetëm atë që thuhet në këtë seri artikujsh, dhe në këtë të dytën, atëherë tashmë mund të shkruani diçka të dobishme. Përpara është pjesa e tretë, pasi të kuptoni të cilën do të mësoni se si të kaloni parametrat dhe çelësat e linjës së komandës në skriptet bash dhe çfarë të bëni me të gjitha.

Një përshkrim i shkurtër i ndryshimit në llojet e lakut:

for - do të kryejë një veprim për sa kohë që ka objekte për të ekzekutuar (për shembull, leximi i një transmetimi nga stdin, një skedar ose një funksion);
ndërsa - kryen veprimin deri në gjendjeështë e vërtetë;
deri - do të ekzekutohet për aq kohë sa gjendje nuk do të bëhet e vërtetë, d.m.th. tani për tani është e rreme.

FOR Loop

Konsideroni këtë version të skenarit me një lak:

$ cat loop.sh #!/bin/bash për variablin në `ls -1` bëj jehonë "$variable" u krye

Sintaksa është shumë e thjeshtë dhe tregohet mjaft qartë në shembull:

variabli for (start the loop) (deklaroni një variabël mbi të cilin do të kryejmë veprime) në (dërgoni një rrjedhë në cikli) `ls -1` (komandë që do të ekzekutohet dhe do t'i kalohet ndryshores $variable). Do dhe done janë "trupi" i ciklit, brenda të cilit do të kryhen veprimet kryesore në të dhënat e marra, dhe jehona "$variable" është veprimi aktual i kryer nga cikli.

Tani le ta ndryshojmë pak shembullin dhe në vend që të specifikojmë në mënyrë eksplicite komandën, do të përdorim variablin e dytë:

$ cat loop.sh #!/bin/bash ls=`ls -1` për variablin në $ls do jehonë "$variable" u krye

Tani komanda ls -1 kalohet në një ndryshore të veçantë, e cila ju lejon të punoni me lak në mënyrë më fleksibël. Në vend të një variabli në një lak, mund të përdorni gjithashtu një funksion:

$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) për variablin në `lsl` bëni jehonë "$variable" u krye

Kushti kryesor i ciklit for është që ai do të ekzekutohet për aq kohë sa komanda e kaluar në të përmban objekte për veprim. Bazuar në shembullin e mësipërm - për sa kohë që ls -1 ka skedarë për të shfaqur - cikli do t'i kalojë ato në një variabël dhe do të ekzekutojë "trupin e lakut". Sapo të përfundojë lista e skedarëve në drejtori, cikli do të përfundojë ekzekutimin e tij.

Le ta bëjmë shembullin pak më të komplikuar.

Drejtoria përmban një listë të skedarëve:

$ ls -1 skedari1 skedari2 skedari3 skedari4 skedari5 loop.sh nofile1 nofile2 nofile3 nofile4 nofile5

Duhet të zgjedhim prej tyre vetëm ato që nuk e kanë fjalën " nr«:

$ cat loop.sh #!/bin/bash lsl=`ls -1` për variablin në $lsl bëj jehonë "$variable" | grep -v "jo" është bërë $ ./loop.sh skedari1 skedari2 skedari3 skedari4 skedari5 loop.sh

Ju gjithashtu mund të përdorni shprehje të kushtëzuara në një lak ( shprehjet e kushtëzuara) [...] për të kontrolluar kushtet dhe deklaratën e ndërprerjes për të ndërprerë ciklin nëse kushti aktivizohet.

Merrni parasysh këtë shembull:

$ cat loop.sh #!/bin/bash lsl=`ls -1` për variablin në $lsl bëj nëse [ $variable != "loop.sh" ] pastaj jehonë "$variable" | grep -v "jo" tjetër thyej fi bërë

Cikli do të vazhdojë derisa të ndeshet skedari loop.sh. Sapo ekzekutimi i ciklit të arrijë këtë skedar, cikli do të ndërpritet nga komanda break:

$ ./loop.sh skedari1 skedari2 skedari3 skedari4 skedari5

Një shembull tjetër është përdorimi i operacioneve aritmetike menjëherë përpara ekzekutimit të trupit të lakut:

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

Këtu kemi vendosur tre komanda kontrolli - count=1, një kusht kontrollues - ndërsa numërimi është më i vogël se 11 dhe një komandë për të ekzekutuar - count +1:

WHILE dhe DERI sythe

Një shembull i thjeshtë që tregon qartë se si funksionon cikli while:

$ cat loop.sh #!/bin/bash count=0 ndërsa [ $count -lt 10 ] bëj ((count++)) echo $count kryer

Ne e vendosim variablin $count në zero dhe më pas ekzekutojmë ciklin whi le me kushtin "ndërsa $count është më pak se dhjetë, ekzekutoni ciklin". Në trupin e lakut ne ekzekutojmë shtim postfiks+1 në ndryshoren $count dhe rezultati printohet në stdout.

Rezultati i ekzekutimit:

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

Sapo vlera e ndryshores $count u bë 10, cikli u ndal.

Një shembull i mirë i një cikli "të pafund" që tregon se si funksionon ndërsa:

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

Cikli deri punon në mënyrë të ngjashme, por në drejtim të kundërt:

$ cat loop.sh #!/bin/bash count=0 derisa [ $count -gt 10 ] të bëjë ((count++)) echo $count përfunduar

Këtu vendosim një kusht të ngjashëm, por në vend të "ndërsa ndryshorja është më e vogël se 10", ne specifikojmë "derisa ndryshorja të bëhet më e madhe se 10". Rezultati i ekzekutimit:

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

Nëse shembulli i mësipërm i një "ciku të pafund" ekzekutohet duke përdorur deri, ai nuk do të nxjerrë asgjë, ndryshe nga ndërsa:

$ cat loop.sh #!/bin/bash count=10 derisa [ 1 = 1 ] të bëjë ((count++)) echo $count kryer $ ./loop.sh $

sepse " gjendje"fillimisht" e vërtetë"—trupi i lakut nuk do të ekzekutohet.

Ashtu si në ciklin for, ju mund të përdorni funksionet në while dhe deri. Për shembull, një lak nga një skript i jetës reale që kontrollon statusin e serverit Tomcat(PID është marrë nga sistemi SLES, mund të ndryshojë në sisteme të tjera), një version pak i thjeshtuar:

$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) ndërsa check_tomcat_status bëni nëse [ -n "$ RUN" ] pastaj printf "PARALAJMËRIM: Tomcat ende funksionon me PID $RUN."

Rezultati i ekzekutimit:

else printf "Tomcat ndaloi, po vazhdon...nn" pushimi u krye

$ ./loop.sh PARALAJMËRIM: Tomcat ende funksionon me PID 14435 26548. PARALAJMËRIM: Tomcat ende funksionon me PID 14435 26548. PARALAJMËRIM: Tomcat ende funksionon me PID 14435 26548. PARALAJMËRIM: Tomcat ende po punon me PID 14435 26548. funksionon me PID 14435 26548. PARALAJMËRIM: Tomcat ende funksionon me PID 14435 26548. PARALAJMËRIM: Tomcat ende funksionon me PID 14435 26548. PARALAJMËRIM: Tomcat ende funksionon me PID 14435

Versioni i plotë:

Check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) ndërsa check_tomcat_status; bëj nëse [ -n "$RUN" ] atëherë printf "PARALAJMËRIM: Tomcat po funksionon ende me PID $RUN. Ndalo? " përgjigju "Ndalimi i Tomcat..." "Vazhdon instalimi..." && $CATALINA_HOME/bin/shutdown sh 2&>1 /dev/null || thyej gjumin 2 nëse [ -n "$RUN" ] atëherë printf "Tomcat ende po funksionon. Vrite atë? " përgjigju "Killing Tomcat..." "Po vazhdon instalimi...n" && vras ​​$RUN || pushim fjetje 2 fi other printf "Tomcat ndaloi, po vazhdon...nn" pushim fi e kryer

Funksioni i përgjigjes u përshkrua në artikull, por këtu përdoret një version pak i përmirësuar:

Përgjigjuni () (ndërsa përgjigjen e lexoni; bëni echo case $response në |) printf "$1n" ktheni 0 pushim ;;

5

|) printf "$2n" ktheje 1 pushim ;;

*) printf "Ju lutemi, shkruani Y(po) ose N(jo)! " esac përfunduar )

Këtu ishte e mundur të përdorej si while ashtu edhe deri - por jo një lak for, pasi for do të kishte funksionuar një herë (mori PID dhe mbaroi).

1) Skripti juaj është i koduar në një mënyrë të rrezikshme. Së pari, po supozoj se po përdorni guaskën Bash pasi e keni shënuar me "/bash" dhe "/for". Në përgjigjen time do të citoj këtë udhëzues të shkëlqyer Bash, i cili është ndoshta burimi më i mirë për të mësuar Bash.

Konkretisht, $(find$ DIRWORK -type d -name work) dhe $(find$ DIR -type f) do t'i nënshtrohen ndarjes së fjalëve, pra nëse find gjen një skedar me hapësira në emrin e tij, d.m.th. "filename" rezultati i ndarjes së fjalës Bash do t'i kalojë 2 argumente komandës për për t'u përsëritur, d.m.th. një për "skedarin" dhe një për "emrin". Në këtë rast, ju dëshironi të shpresoni që të merrni "skedar: nuk ka skedar ose drejtori të tillë" dhe "emri: nuk ka skedar ose drejtori të tillë" në vend që t'i dëmtoni ato nëse ekzistojnë në të vërtetë.

2) Sipas konventës, variablat e mjedisit (PATH, EDITOR, SHELL, ...) dhe variablat e brendshëm të guaskës (BASH_VERSION, RANDOM, ...) janë me shkronjë të plotë. Të gjithë emrat e variablave të tjerë duhet të jenë me shkronja të vogla. Për shkak se emrat e variablave janë të ndjeshëm ndaj shkronjave të vogla, kjo konventë shmang tejkalimin aksidental të ndryshoreve mjedisore dhe të brendshme.

Ky është një version më i sigurt i skriptit tuaj, të cilin ju rekomandoj ta përdorni në vend të kësaj:

My_home="/root/mydir" my_dir=" $my_home/var" dir_work="$ my_home/Local" ndërsa IFS= read -r -d "" f; bëj # Unë hamendësoj se ju gjithashtu dëshironi të injoroni stderr; # këtu erdhi 2>&1. nëse lsof -n "$f" | grep "" > /dev/null 2> atëherë bëni jehonë "hej , Unë "Unë jam më i sigurt tani!"< <(find "$ dir_work" -type f -print0) while IFS= read -r -d "" f; do echo "2" done < <(find "$dir_work" -type d -name "work" -print0)

fi bërë

Siç mund ta shihni, ndryshorja IFS është vendosur të zbrazet, duke parandaluar kështu që leximi të shkurtojë hapësirën e përparme dhe të pasme nga rreshti. Komanda read përdor rreshtin bosh (-d "") si ndarës për të lexuar derisa të arrijë a\0, gjetja duhet të jetë m në përputhje me rrethanat, kështu që përdor opsionin -print0 për të ndarë të dhënat e saj me \0 në vend të një rreshti të ri. , çuditërisht dhe me qëllim të keq, mund të jetë pjesë e emrit të skedarit. Ndarja e një skedari të tillë \n në dy pjesë do të thyejë kodin tonë.

Përgjigja e mëparshme ku thuhej se gjeni... | ndërsa lexoni emrin; bëj ...; bërë duhet të përdoret për të lexuar gjetjen e prodhimit mund të jetë gjithashtu i keq. Cikli while ekzekutohet në një nënpredhë të re me kopjen e vet të variablave të kopjuar nga prindi i tij. Kjo kopje më pas përdoret për çdo gjë që ju pëlqen. Kur cikli while të përfundojë, kopja e nënshtresës do të hidhet poshtë dhe variablat origjinale të prindit nuk do të modifikohen.

0

"Asnjëherë mos përdorni zëvendësimin e komandës, të asnjë lloji, pa thonjëza." Kjo është thjesht gërmuese, por është e mundur të përdoret zëvendësimi i komandës pa thonjëza kur vendosni një ndryshore: "diçka = $(emri bazë" emri i skedarit me hapësira ")". - Smith John 22 Prill 13 2013-04-22 21:43:10

2

Për i në $(gjeni$ DIRWORK -type d -emri i punës); bëj jehonë "2" bërë

do të jetë i pari që do të ekzekutojë këtë linjë

Gjeni punën $DIRWORK -type d -name

prisni derisa gjetja të përfundojë ekzekutimi dhe më pas merrni një ditë pushim dhe vendoseni përsëri në ciklin për

Për i në daljen e gjeni; bëj jehonë "2" e kryer

vetëm atëherë cikli for do të fillojë të ekzekutohet.

Pra, nëse gjetja kërkon shumë kohë për të përfunduar ciklin e saj për, duhet të presë një kohë të gjatë përpara se të fillojë.

Provoni komandat e përkohshme të gjetjes në mënyrë interaktive

$ kohë gjeni $DIRWORK -tipi d -emri i punës

dhe shikoni sa kohë duhet.

Gjithashtu vini re: nuk duhet të përdorni një cikli for për të përsëritur mbi emrat e skedarëve. Përdorni një lak while me leximin si kjo:

Gjeni$ DIRWORK -tipi d -emri i punës | ndërsa lexoni emrin; bëj jehonë "2" e kryer

Bonusi: ai drejton një cikli while paralelisht me find . Kjo do të thotë që cikli while do të përfundojë një përsëritje sapo find të printojë një rresht. Nuk ka nevojë të presësh për gjetjen për të përfunduar ekzekutimin.

Në këtë ligjëratë vazhdojmë të njihemi me bash. Dua t'ju kujtoj se ne jemi duke i shqyrtuar ato elemente bash, e cila do të na ndihmojë të kuptojmë skriptet e sistemit operativ. Elementë të tillë janë padyshim sythe dhe funksione. Nëse dikush ka studiuar programim, atëherë nuk do të ketë vështirësi në kuptimin e këtyre pyetjeve.

për lak

Cikli për V bash ka dy lloje. Le të shohim së pari versionin klasik për. Pamja e përgjithshme është si më poshtë:

Midis elementeve për Dhe vendoset një variabël, i cili nga ana tjetër merr një vlerë nga sekuenca e vlerave të specifikuara ndërmjet Dhe bëj. ndërmjet bëj Dhe bërë ka komanda që ekzekutohen sa herë që një ndryshore ndryshon vlerën e saj. Cikli ndalon kur ndryshorja merr vlerën e fundit nga sekuenca. Vlerat në sekuencë ndahen me hapësira.

Këtu është një shembull praktik:

Sekuenca e vlerave mund të specifikohet në mënyra të ndryshme. Në mënyrë eksplicite - si në shembullin e mësipërm, ose duke përdorur ndryshore të tjera, ose duke përdorur komanda të veçanta. Le të shohim disa shembuj. Meqenëse vlerat përcaktohen të ndara me hapësira, vlera të tilla mund të jenë çdo variabël që përmban një varg me hapësira:

Rezultati do të jetë i njëjtë si në shembullin e parë.

Nëse keni nevojë të specifikoni një sekuencë numrash, mund të përdorni komandën vijim dhe një mekanizëm zëvendësues. Ekipi vijim kthen një sekuencë vlerash numerike në ekran. Sintaksa është e thjeshtë dhe do të jetë e qartë nga shembulli më poshtë:

Rezultati:

Le të kthehemi te lloji i dytë për. Shpesh në skriptet mund të gjeni të ashtuquajturin variant të ngjashëm me C për, i cili përdoret për sythe të bazuara në numra. Le të hedhim një vështrim në një shembull:

Cikli funksionon për sa kohë që kushti që testohet në shprehje është i vërtetë. Sapo shprehja kthehet false, ekzekutimi i lakut ndalon.

Shembull praktik:

#!/bin/bash
i=1
ndërsa [ $i -lt 7 ]
bëj
jehonë $i
le të i=i+1
bërë

Në shembullin tonë, ne kontrollojmë që ndryshorja iështë më i vogël se (-lt) numri 7 dhe nëse po, atëherë në ekran shfaqet vlera e ndryshores. Shprehje le të i=i+1, rrit variablin me një, kontrollon përsëri, etj. let i thotë interpretuesit se argumentet duhet të njihen si vlera numerike. Ky rresht mund të shkruhet si le i++(variant i ngjashëm me c). Kur një numër rritet me më shumë se një, ai mund të shkruhet kështu: le i+=2- në këtë rast i do të rritet në rritje prej 2. Një tjetër mundësi për rritjen e një ndryshoreje është përdorimi i kalkulatorit të integruar (funksionon vetëm me numra të plotë). Llogaritësi mund të arrihet përmes kllapave të dyfishta: i=$(($i+1)) ose përmes katrorëve: i=$[$i+1] Ju gjithashtu mund të përdorni kalkulatorin në vijën e komandës:

Duhet të keni kujdes me sythe në mënyrë që të mos përfundoni me një lak pa fund. Nga rruga për korrigjimin e gabimeve bash skriptet në të cilat mund të ndryshoni rreshtin e parë #!/bin/bash -x ose ekzekutoni skriptin me komandën bash -x:

igor@ubuntu:~/linux$ bash -x ./testfor.sh
+ i=1
+ '[' 1 -gt 5 ']'
+ jehonë i=1
i=1
+ le të i=i+1
+ '[' 2 -gt 5 ']'
+ jehonë i=2
i=2
+ le të i=i+1
+ '[' 3 -gt 5 ']'
+ jehonë i=3
i=3
+ le të i=i+1
+ '[' 4 -gt 5 ']'
+ jehonë i=4
i=4
+ le të i=i+1
+ '[' 5 -gt 5 ']'
+ jehonë i=5
i=5
+ le të i=i+1
+ '[' 6 -gt 5 ']'

Sigurohuni që të praktikoni shkrimin e skripteve të vogla për të përforcuar të kuptuarit tuaj se si funksionojnë unazat bash.

Funksionon në bash

Funksionet përdoren në bash shumë e gjerë. Funksionet përshkruhen në dy mënyra: me një fjalë kyçe funksionin, dhe pa të.

Mënyra e parë:

funksioni_emri i funksionit
{
trupi i funksionit
}

Mënyra e dytë:

emri_funksionit()
{
trupi i funksionit
}

Një funksion thirret me emër kudo në skript, por vetëm pasi të përshkruhet vetë funksioni. Funksioneve mund t'u kalohen edhe parametrat, të cilët specifikohen të ndara me një hapësirë ​​pas thirrjes së funksionit (emrit). Le të shohim një shembull skenari bash:

#!/bin/bash
abetare funksioni
{
nëse [$# -ne 0 ]
pastaj
lokale a=1
echo "Numri i parametrave të kaluar - $#"
për mua në $@
bëj
echo "parametri $a-th është $i"
le një ++
bërë
kthimi 0
tjetër
jehona "Parametrat nuk u kaluan"
kthimi 1
fi
}
echo "Thirrni një funksion me parametra:"
abetare a b c
jehonë $?
echo "Thirrni një funksion pa parametra:"
abetare
jehonë $?

Në këtë shembull, një funksion me emrin abetare. Thirrja e një funksioni me parametra: abetare a b c dhe pa parametra: abetare. Në trupin e funksionit, të gjitha ndërtimet duhet të jenë të njohura për ju, me përjashtim të $# , $i Dhe $@ .$# — kthen numrin e parametrave të kaluar në funksion. Në shembullin tonë ky do të jetë një numër 3 .$@ kthen të gjithë parametrat në një rresht. Në shembull do të ishte a b c. Dhe përmes $1 , $2 , $3 etj. Ju mund të përdorni çdo parametër individualisht. $? — përmban kodin e ekzekutimit të komandës së fundit. Në shembullin tonë, kodi i ekzekutimit të funksionit.

Funksioni gjithashtu mund të kthejë një vlerë numerike nëpërmjet një fjale kyçe kthimi. Zakonisht ata kthejnë 0 nëse funksioni ekzekutohet pa gabime ose një vlerë jo zero nëse diçka shkon keq. Në shembull, nëse një funksion thirret me parametra, kthehet vlera 0, dhe nëse funksioni thirret pa parametra, kthehet kodi 1.

Çdo gjë në lidhje me kalimin e parametrave në një funksion funksionon saktësisht njësoj për një skript. Ju gjithashtu mund t'i kaloni parametrat skriptit dhe t'i manipuloni ato në të njëjtën mënyrë duke përdorur $#, $@, $N. Nga e njëjta kategori është opsioni - $0 - e cila kthen emrin e komandës që nisi skriptin. Nëse skripti drejtohej me komandë ./skript.sh, pastaj jehonë $0 do të kthejë vlerën ./skript.sh, dhe nëse me komandë /home/igor/linux/script.sh, atëherë vlera do të kthehet /home/igor/linux/script.sh.

© 2024 ermake.ru -- Rreth riparimit të PC - Portali informacioni