Shell script-urile sunt utilizate pe scară largă în lumea UNIX. Sunt excelente pentru accelerarea sarcinilor repetitive și simplificarea logicii complexe de execuție. Ele pot fi la fel de simple ca un set de comenzi sau pot orchestra sarcini complexe. În acest tutorial, vom afla mai multe despre limbajul de scripting Bash scriind un exemplu de script pas-cu-pas.
Una dintre cele mai bune modalități de a învăța despre o nouă limbă este de exemplu. Să începem cu una.
Problema Fizz-Buzz este una foarte simplă. A devenit faimos după ce un programator, pe nume Imran, a folosit-o ca test de interviu. Se pare că 90-99,5% dintre candidații la un post de programare nu pot scrie singur cel mai simplu program. Imran a luat acest simplu joc Fizz-Buzz și ia cerut candidații să o rezolve. Mulți au urmat exemplul lui Imran și, astăzi, este una dintre cele mai solicitate întrebări frecvente pentru un program de programare. Dacă angajați și aveți nevoie de o modalitate de a filtra peste 90% dintre candidați, este o problemă importantă de prezentat.
Iată regulile:
Cam despre asta e. Sunt sigur că majoritatea dintre voi puteți vizualiza deja cele două sau trei dacă
declarații pentru a rezolva acest lucru. Să lucrăm prin aceasta folosind limbajul de scripting Bash.
Un shebang se referă la combinația dintre caracterele hash și exclamation mark: #!
. Încărcătorul de programe va căuta un shebang pe prima linie a scriptului și va folosi interpretul specificat în el. Un shebang constă din următoarea sintaxă: #!interpret [parametri]
. Interpretul este programul folosit pentru interpretarea limbii noastre. Pentru scripting-ul bash, asta ar fi / Bin / bash
. De exemplu, dacă doriți să creați un script în PHP și să îl rulați în consola, probabil că doriți să îl utilizați / Usr / bin / php
(sau calea către executabilul PHP pe mașina dvs.) ca interpret.
#! / Usr / bin / phpDa, asta va funcționa! Nu este simplu? Doar asigurați-vă că faceți fișierul executabil mai întâi. Odată ce faceți, acest script va afișa informațiile dvs. PHP așa cum v-ați aștepta.
Bacsis: Pentru a vă asigura că scriptul dvs. va funcționa pe cât mai multe sisteme posibil, puteți utiliza
/ Bin / env
în shebang. Ca atare, în loc de/ Bin / bash
, ai putea folosi/ bin / env bash
, care va funcționa pe sisteme în care executabilul bash nu se află înăuntru/cos
.
Rezultatul textului
Ieșirea unui script va fi egală cu, după cum s-ar putea aștepta, tot ce este afișat din comanda. Cu toate acestea, dacă vrem în mod explicit să scriem ceva pe ecran, putem folosi
ecou
.#! / bin / bash ecou "Hello World"Rularea acestui script va imprima "Hello World" în consola.
csaba @ csaba ~ $ ./helloWorld.sh Buna ziua csaba @ csaba ~ $
Introducerea variabilelor
Ca și în cazul oricărui limbaj de programare, când scrieți scripturile shell, puteți utiliza variabilele.
#! / bin / bash message = mesajul "Hello World" echo $Acest cod produce exact același mesaj "Hello World". După cum puteți vedea, pentru a atribui o valoare unei variabile, scrieți doar numele - excludeți semnul dolarului în fața acesteia. De asemenea, aveți grijă cu spațiile; nu pot exista spații între numele variabilei și semnul egal. Asa de
Mesajul = „Bună ziua“
in loc demesaj = 'Hello'
Când doriți să utilizați o variabilă, puteți lua valoarea din ea la fel cum am făcut în
ecou
comanda. Prependând a$
la numele variabilei va returna valoarea sa.Bacsis: În ecranul bash nu sunt necesare punctajele punctuale. Puteți să le folosiți în majoritatea cazurilor, dar aveți grijă: pot avea un înțeles diferit de ceea ce vă așteptați.
Imprimarea numerelor între 1 și 100
Continuând cu demo-ul nostru, trebuie să trecem prin toate numerele între 1 și 100. Pentru aceasta, va trebui să folosim un
pentru
buclă.#! / bin / bash pentru numărul în 1 ... 100; se face echo $ numărul făcutExistă mai multe lucruri noi care merită notate în acest exemplu - care, apropo, imprimă toate numerele de la 1 la 100, câte un număr simultan.
pentru
sintaxa în Bash este: pentru VARIABLE in RANGE; face COMMAND făcut
.1 ... 100
într-o gamă în exemplul nostru. Ele sunt folosite și în alte contexte, pe care le vom examina în scurt timp.do
și pentru
sunt de fapt două comenzi separate. Dacă doriți să plasați două comenzi pe o singură linie, va trebui să le separați cumva. O modalitate este de a utiliza punct și virgulă. Alternativ, ați putea scrie codul fără punct și virgulă prin deplasare do
la următoarea linie.#! / bin / bash pentru numărul din 1 ... 100 nu efectuați echo $ numărul
Acum că știm cum să tipărim toate numerele între 1 și 100, este timpul să luăm prima noastră decizie.
#! / bin / bash pentru numărul în 1 ... 100; dacă [$ ((număr% 3)) -eq 0]; apoi echo "Fizz" altceva echo $ numărul fi făcut
Acest exemplu va scoate "Fizz" pentru numere divizibile prin 3. Din nou, trebuie să ne ocupăm de o sintaxă nouă. Să le luăm unul câte unul.
dacă ... atunci ... altceva ... fi
- aceasta este sintaxa clasică pentru o dacă
declarație în Bash. Desigur, altfel
parte este opțională - dar este necesară pentru logica noastră în acest caz.dacă valoarea COMMAND-RETURN-VALUE; atunci…
- dacă
va executa dacă valoarea de retur a comenzii este zero. Da, logica în Bash este bazată pe zero, ceea ce înseamnă că comenzile care execută ieșirea cu succes cu un cod de 0. Dacă ceva nu merge bine, pe de altă parte, un întreg pozitiv va fi returnat. Pentru a simplifica lucrurile: se ia în considerare orice altceva decât 0 fals
.$ ((Număr% 3))
va returna valoarea rămasă de împărțire a variabilei, număr
, de 3. Vă rugăm să rețineți că nu am folosit $
în interiorul parantezei - numai în fața lor.S-ar putea să te întrebi unde este comanda în exemplul nostru. Nu este doar o coadă cu o expresie ciudată în ea? Ei bine, se pare asta [
este de fapt o comandă executabilă. Pentru a juca cu asta, încercați următoarele comenzi în consola dumneavoastră.
csaba @ csaba ~ $ care [/ usr / bin / csaba @ csaba ~ $ [0 -eq 1] csaba @ csaba ~ $ echo $? 1 csaba @ csaba ~ $ [0 -eq 0] csaba @ csaba ~ $ echo $? 0
Bacsis: Valoarea de ieșire a unei comenzi este întotdeauna returnată în variabilă,
?
(semnul întrebării). Acesta este suprascris după executarea fiecărei noi comenzi.
Mergem bine până acum. Avem "Fizz"; acum să facem partea "Buzz".
#! / bin / bash pentru numărul în 1 ... 100; dacă [$ ((număr% 3)) -eq 0]; apoi echo "Fizz" elif [$ ((număr% 5)) -eq 0]; apoi echo "Buzz" altceva echo $ numărul fi făcut
Mai sus, am introdus o altă condiție pentru divizibilitate cu 5: Elif
afirmație. Acest lucru, desigur, se traduce la altfel dacă, și va fi executat dacă se întoarce comanda care o urmează Adevărat
(sau 0
). După cum puteți observa, afirmațiile condiționale din interiorul []
sunt de obicei evaluate cu ajutorul unor parametri, cum ar fi -eq
, care înseamnă "egal".
Pentru sintaxa,
arg1 OP arg2
,OP
este unul din-eq
,-ne
,-lt
,-Le
,-gt
, sau-GE
. Acești operatori binari aritmetici se întorcAdevărat
dacăARG1
este egal cu, nu egal cu, mai mic, mai mic sau egal cu, mai mare sau mai mare sau egal cuarg2
, respectiv.ARG1
șiarg2
pot fi numere întregi pozitive sau negative. - Bash Manual
Când încercați să comparați șiruri de caractere, puteți utiliza cele cunoscute ==
semn, sau chiar un singur semn egal va face. !=
se intoarce Adevărat
când șirurile sunt diferite.
Până în prezent, codul rulează, dar logica nu este corectă. Când numărul este divizibil de ambele 3 și 5, logica noastră va econa doar "Fizz". Să modificăm codul nostru pentru a satisface ultima cerință a FizzBuzz.
#! / bin / bash pentru numărul în 1 ... 100; dacă [$ ((număr% 3)) -eq 0]; apoi output = "Fizz" fi dacă [$ ((număr% 5)) -eq 0]; apoi output = "$ output Buzz" fi dacă [-z $ output]; apoi echo $ un număr altceva echo $ output; fi făcut
Din nou, a trebuit să facem o serie de schimbări. Cel mai notabil este introducerea unei variabile și apoi concatenarea lui "Buzz", dacă este necesar. Strings in bash sunt de obicei definite intre ghilimele duble (") .Cotatiile simple sunt de asemenea folosite, dar pentru o concatenare mai usoara, dublele sunt cea mai buna alegere. un text $ variabilă alt text
" voi inlocui $ variabila
cu conținutul său. Când doriți să concatenați variabilele cu șiruri de caractere fără spații între ele, puteți prefera să puneți numele variabilei în coarde curbate. În cele mai multe cazuri, cum ar fi PHP, nu sunteți obligat să faceți acest lucru, dar ajută foarte mult la citirea codului.
Bacsis: Nu puteți compara corzile goale. Acest lucru va returna un parametru lipsă.
Deoarece argumentele din interior []
sunt tratate ca parametri, pentru "["
, acestea trebuie să fie diferite de un șir gol. Deci, această expresie, chiar dacă este logică, va produce o eroare: [$ output! = ""]
. De aceea am folosit-o [-z $ ieșire]
, care se întoarce Adevărat
dacă șirul are o lungime de zero.
O modalitate de a ne îmbunătăți exemplul este să extragem în funcții expresia matematică din dacă
declarații, cum ar fi:
Funcția #! / bin / bash esteDivisibleBy retur $ (($ 1% $ 2)) pentru numărul în 1 ... 100; dacă este isDivisibleBy $ numărul 3; apoi output = "Fizz" fi dacă esteDivisibleBy $ numărul 5; apoi output = "$ output Buzz" fi dacă [-z $ output]; apoi echo $ un număr altceva echo $ output; fi făcut
Am luat expresiile comparând restul cu zero și le-am transferat într-o funcție. Mai mult, am eliminat comparația cu zero, deoarece zero înseamnă adevărat pentru noi. Trebuie doar să întoarcem valoarea din expresia matematică - foarte simplă!
Bacsis: Definirea unei funcții trebuie să fie precedată de apelul acesteia.
În Bash, puteți defini o metodă ca funcția func_name comenzi;
. Opțional, există oa doua sintaxă pentru declararea funcțiilor: func_name () comenzi;
. Deci, putem lăsa șirul, funcţie
si adauga "()"
după numele său. Eu personal prefer această opțiune, așa cum este exemplificat în exemplul de mai sus. Este mai explicit și seamănă cu limbile de programare tradiționale.
Nu este necesar să specificați parametrii pentru o funcție în Bash. Trimiterea parametrilor către o funcție este realizată prin simpla enumerare a acestora după ce apelul funcției este separat de spații albe. Nu introduceți virgule sau paranteze în apelul funcției - nu va funcționa.
Parametrii primiți sunt atribuiți automat variabilelor după număr. Primul parametru merge la $ de 1
, al doilea la $ cu 2
, si asa mai departe. Variabila specială, $ cu 0
se referă numele fișierului curent al scriptului.
#! / bin / funcția bash exampleFunc echo $ 1 echo $ 0 IFS = "X" echo "$ @" echo "$ *" exampleFunc "
Acest cod va produce următoarea ieșire:
csaba @ csaba ~ $ ./parametersExamples.sh o ./parametersExamples.sh o două două unuTwtwoXthre
Să analizăm sursa, linie cu linie.
$ @
. Acesta reprezintă toți parametrii ca un singur cuvânt, exact așa cum este specificat în apelul pentru funcții.$ *
. Acesta reprezintă toți parametrii, luați unul câte unul și concatenat cu prima literă a variabilei IFS. De aceea rezultatul este oneXtwoXthre
.După cum am observat mai devreme, funcțiile din Bash pot întoarce numai numere întregi. Ca atare, scris retur "un șir"
ar fi codul nevalid. Cu toate acestea, în multe situații, aveți nevoie de mai mult de un zero sau unul. Putem să refacem exemplul nostru FizzBuzz astfel încât, în pentru
declarație, vom face doar un apel de funcție.
Funcția #! / bin / bash esteDivisibleBy return $ (($ 1% $ 2)) funcția fizzOrBuzz ifDivisibleBy $ 1 3; apoi output = "Fizz" fi dacă isDivisibleBy $ 1 5; apoi output = "$ output Buzz" fi dacă [-z $ output]; apoi echo $ 1 altceva echo $ output; fi pentru numărul din 1 ... 100; face fizzOrBuzz numărul de $ făcut
Ei bine, acesta este primul pas. Tocmai am extras tot codul într-o funcție numită fizzOrBuzz
, și apoi înlocuit număr $
cu $ de 1
. Cu toate acestea, toate ieșirile apar în fizzOrBuzz
funcţie. Vrem să ieșim din pentru
buclă cu un ecou
, astfel încât să putem prefixa fiecare linie cu un alt șir. Trebuie să capturăm fizzOrBuzz
funcția de ieșire.
# [...] pentru numărul din 1 ... 100; do echo "-'fizzOrBuzz $ number '" fizzBuzzer = $ (fizzOrBuzz $ number) echo "- $ fizzBuzzer" terminat
Ne-am actualizat pentru
bucla doar un pic (nu alte modificări). Acum am reluat totul de două ori în două moduri diferite pentru a exemplifica diferențele dintre cele două soluții la aceeași problemă.
Prima soluție pentru captarea ieșirii unei funcții sau a altei comenzi este folosirea spintecilor. În 99% din cazuri, acest lucru va funcționa foarte bine. Puteți să vă referiți pur și simplu la o variabilă în spate după nume, așa cum am făcut-o număr $
. Primele câteva linii ale producției ar trebui să pară acum:
csaba @ csaba ~ / Personal / Programare / NetTuts / Elementele de bază ale scriptului BASH / surse $ ./fizzBuzz.sh -1 -1 -2 -2 -Fizz -Fizz -4 -4 -Buzz -Buzz -Fizz -Fizz -7 -7
După cum puteți vedea, totul este duplicat. Aceeași ieșire.
Pentru a doua soluție, am ales să atribuim mai întâi valoarea returnată unei variabile. În acea misiune, am folosit $ ()
, care, în acest caz, forks script-ul, execută codul și returnează ieșirea.
Vă amintiți că am folosit punct și virgulă aici și acolo? Acestea pot fi folosite pentru a executa mai multe comenzi scrise pe aceeași linie. Dacă le separați prin punct și virgulă, acestea vor fi pur și simplu executate.
Un caz mai sofisticat este de a utiliza &&
între două comenzi. Da, aceasta este o logică AND; înseamnă că cea de-a doua comandă va fi executată numai dacă primul se întoarce Adevărat
(iese din 0). Acest lucru este util; putem simplifica dacă
declarații în acești concetățeni:
Funcția #! / bin / bash esteDivisibleBy return $ (($ 1% $ 2)) funcția fizzOrBuzz isDivisibleBy $ 1 3 && output = "Fizz" esteDivisibleBy $ 1 5 && output = "$ output Buzz" ]; apoi echo $ 1 altceva echo $ output; fi pentru numărul din 1 ... 100; face ecou "-'fizzOrBuzz $ number '' terminat
Ca funcție, isDivisibleBy
returnează o valoare corespunzătoare retur, pe care o putem folosi ulterior &&
pentru a seta variabila dorită. Ce urmează &&
vor fi executate numai dacă condiția este Adevărat
. În același mod, putem folosi ||
(caracter dublu) ca logic OR. Iată un exemplu rapid de mai jos.
csaba @ csaba ~ $ echo "bubu" || echo "bibi" bubu csaba @ csaba ~ $ echo false || echo "bibi" fals csaba @ csaba ~ $
Așa că face acest lucru pentru acest tutorial! Sper că ați luat o mână de sfaturi și tehnici noi pentru a vă scrie propriile scripturi Bash. Vă mulțumim pentru lectură și rămâneți reglați pentru articole mai avansate pe această temă.