Jump to content
Sign in to follow this  
Bebe

[Info] Programare Shell cu bash

Recommended Posts

Programare Shell cu bash: de exemplu,

prin contra-exemplu

 

 

Ca o coajă interactivă, bash este un limbaj obișnuit pentru inițierea și direcționarea calculelor.

Ca limbaj de script, bash este un limbaj specific domeniului pentru manipularea și compunerea proceselor și fișierelor.


Bash-ul este baroc. Bash este casant. Bash este indispensabil.

Bash nu a fost proiectat.

Nu este corect să spunem că bash a evoluat nici ea: păstrează și folosește toate apendicele sale vestigiale.

Citiți mai departe pentru scurtul meu ghid bazat pe exemple de bash, inclusiv acoperirea de:

variabile și tablouri;
operațiuni pe variabile;
aspecte subtile ca *versus @;
aritmetic;
siruri de caractere;
domeniul de aplicare;
fișiere și redirecționare;
conducte;
procese;
modele;
structuri de control;
capcane.

Am încercat să fac din aceasta o introducere unică, care să cuprindă toate elementele comune și un bun fragment din avansate.

Dacă sunteți nou la programarea Unix și / sau shell, vă recomand să începeți cu:

Un ghid de supraviețuire pentru Unix ; și / sau
Stabilirea în Unix .
Ce este bash?
Bash este un shell interactiv:


Tastați comenzi.

Bash le execută.

Utilizatorii Unix petrec mult timp manipulând fișierele de pe shell.

Ca shell, este disponibil direct prin terminal, atât în Mac OS X (Aplicații> Utilități), cât și în Linux / Unix.

În același timp, bash este și un limbaj de script:


Scripturile Bash pot automatiza rutina sau sarcinile dificile implicate în administrarea sistemelor.

De ce să folosești bash?
Iată exemple de sarcini pentru care puteți utiliza bash:

Orchestrând activitățile de pornire / oprire a sistemului.
Redenumirea automată a unei colecții de fișiere.
Găsirea tuturor fișierelor mp3 duplicate pe un hard disk.
Orchestrând o suită de instrumente pentru crearea unei baze de date cu parole.
Găsirea cuvintelor nevăzute în scrisul tău.
Implementarea unei baze de date relaționale din fișierele text.
Simplificarea configurației și reconfigurării software-ului.
Bash ca limbaj de script
Pentru a crea un script bash, plasați #!/bin/bash în partea de sus a fișierului.

Apoi, schimbați permisiunile din fișier pentru a-l face executabil:

$ chmod u + x nume de script
Pentru a executa scriptul din directorul curent, puteți rula și trece orice parametru doriți. ./scriptname

Când shell-ul execută un script, acesta găsește . #!/path/to/interpreter

Apoi rulează interpretul (în acest caz /bin/bash) pe fișierul în sine.

#!Convenția este motivul pentru care atât de multe limbaje de scripting folosesc #pentru comentarii.

Iată un exemplu de script bash care tipărește primul argument:

#! / Bin / bash


# Utilizați $ 1 pentru a obține primul argument:
ecou $ 1
Comentarii
Comentariile în bash încep cu #și rulează până la sfârșitul liniei:

ecou Bună ziua, lume. # tipărește „Hello, World”.
Variabile / Arrays
Variabilele în bash au o dublă natură atât ca tablouri cât și ca variabile.

Pentru a seta o variabilă, utilizați =:

 foo = 3 # setează foo la 3
Dar, asigurați-vă că evitați să folosiți spații:

 foo = 3 # eroare: invocă comanda `foo 'cu argumente` =' și `3 '
Dacă doriți să utilizați un spațiu, puteți să vă scufundați în sub-limbajul de expresie care există în interior (( și )):

 ((foo = 3)) # Setează foo la 3.
Pentru a face referire la valoarea unei variabile, utilizați un semn dolar $:

ecou $ foo; # tipărește valoarea foo pentru stdout
Puteți șterge o variabilă cu unset:

 foo = 42
 ecou $ foo # imprimeuri 42
 nesimțit foo
 echo $ foo # tipărește nimic
Desigur, puteți atribui o variabilă alteia:

 foo = $ bar # atribuie valoarea lui $ bar lui foo.
Dacă doriți să atribuiți o valoare care conține spații, asigurați-o că o citați:

 # gresit:
 foo = xyz # setează foo pe x; va încerca să execute y pe z

 # dreapta:
 foo = "xy z" # setează foo pe "xy z"

Uneori este necesar să înfășurați o referință la o variabilă este bretele:

 ecou $ {foo} # imprimeuri $ foo
Această notare este necesară pentru operații și tablouri variabile.

Nu este necesară declararea unei variabile ca tablou: fiecare variabilă este un tablou.

Puteți începe să utilizați orice variabilă ca matrice:

 foo [0] = "primul" # stabilește primul element la "primul"
 foo [1] = "secund" # stabilește cel de-al doilea element pe "al doilea"
Pentru a face referire la un index, folosiți notarea bretele:

 foo [0] = "unu"
 foo [1] = "doi"
 ecou $ {foo [1]} # tipărește „două”

Când faceți referință la o variabilă, aceasta este o referință implicită la primul index:

 foo [0] = "unu"
 foo [1] = "doi"
 ecou $ foo # tipărește „unul”
Puteți utiliza, de asemenea, paranteze pentru a crea un tablou:

 foo = ("aa a" "bb b" "cc c")
 echo $ {foo [2]} # imprimeuri „cc c”
 ecou $ foo # imprimeuri „aa a”
Pentru a accesa toate valorile dintr-un tablou, utilizați abonamentul special @sau *:

 array = (abc)
 ecou $ array # imprimeuri a
 echo $ {array [@]} # imprimeuri abc
 echo $ {array [*]} # imprimeuri abc

Pentru a copia un tablou, utilizați abonament @, înconjurați-l cu ghilimele și înconjurați-l cu paranteze:

 foo = (abc)
 bar = ( "$ {foo [@]}")
 echo $ {bar [1]} # imprimeuri b
Nu încercați să copiați doar variabila:

 foo = (abc)
 bar = $ foo
 echo $ {bar [1]} # nu tipărește nimic

Și nu uitați ghilimelele sau altfel se vor înșela tablouri cu elemente care conțin spațiu:

 foo = ("a 1" "b 2" "c 3")
 bar = ($ {foo [@]})
 Baz = ( "$ {foo [@]}")
 ecou $ {bar [1]} # oops, imprimați „1”
 ecou $ {baz [1]} # imprimeuri "b 2"
Variabile speciale

Există variabile de bază speciale pentru preluarea argumentelor la scripturi și funcții:

 echo $ 0 # tipărește numele scriptului

 echo $ 1 # tipărește primul argument
 echo $ 2 # tipărește al doilea argument
 echo $ 9 # tipărește cel de-al nouălea argument
 echo $ 10 # tipărește primul argument, urmat de 0 
 echo $ {10} # tipărește al zecelea argument

 echo $ # # tipărește numărul de argumente
Variabila $?păstrează „starea de ieșire” a procesului executat anterior.

O stare de ieșire de 0 indică procesul „reușit” fără eroare.

O stare de ieșire, alta decât 0, indică o eroare.

În programarea shell, trueeste un program care „reușește” întotdeauna și falseeste un program care „eșuează” întotdeauna:

 Adevărat
 ecou $? # imprimeuri 0

 fals
 ecou $? # nu va tipări niciodată 0; de obicei tipărește 1
ID-ul procesului actualului shell este disponibil ca $$

ID-ul procesului din cel mai recent proces cu fundal este disponibil ca $!:

 # sortează două fișiere în paralel:
 sortare cuvinte> cuvinte sortate & proces de fundal lansare #
 p1 = $!
 sortare numere-n> numere sortate și # proces de fundal de lansare
 p2 = $!
 așteptați $ p1
 așteptați $ p2
 ecou Ambele fișiere au fost sortate.
Operațiuni asupra variabilelor

Într-o caracteristică unică în multe limbi, bash poate funcționa pe valoarea unei variabile în timp ce abandonează acea variabilă.

Înlocuirea șirurilor
Bash poate înlocui un șir cu un alt șir:

 foo = "Sunt o pisica".
 ecou $ {foo / pisică / câine} # amprentele „Sunt câine”.
Pentru a înlocui toate instanțele unui șir, utilizați clape duble:

 foo = "Sunt o pisică, iar ea este pisica".
 ecou $ {foo / pisică / câine} # amprentele „Sunt un câine și ea este o pisică”.
 ecou $ {foo // pisică / câine} # imprimeuri „Sunt un câine și ea este un câine”.
În general, aceste operații nu modifică variabila:

 foo = "hello" 
 ecou $ {foo / salut / goodbye} # imprimeuri „la revedere”
 ecou $ foo # încă imprimă „salut”
Fără înlocuire, se șterge:

 foo = "Imi plac chiftelutele."
 ecou $ {foo / balls} # imprimeuri îmi place carnea.

Operațiune elimină cel mai scurt prefix de potrivire , în timp ce elimină cea mai lungă: ${name#pattern}${name}pattern##

 minipath = "/ usr / bin: / bin: / sbin"
 ecou $ {minipath # / usr} # printuri / bin: / bin: / sbin
 ecou $ {minipath # * / bin} # printuri: / bin: / sbin
 ecou $ {minipath ## * / bin} # printuri: / sbin
Operatorul %este același, cu excepția sufixelor în locul prefixelor:

 minipath = "/ usr / bin: / bin: / sbin"
 echo $ {minipath% / usr *} # nu tipărește nimic
 echo $ {minipath% / bin *} # printuri / usr / bin:
 ecou $ {minipath %% / bin *} # printuri / usr
Manipularea șirurilor / tablelor

Bash are operatori care operează atât pe tablouri cât și pe șiruri.

De exemplu, operatorul prefixului #numără numărul de caractere dintr-un șir sau numărul de elemente dintr-un tablou.

Este o greșeală obișnuită să operezi accidental pe primul element al unui tablou ca șir, când intenția era să funcționeze pe tablou.

Chiar și Ghidul Bash pentru începători conține un exemplu înșelător:

 ARRAY = (unu două trei)
 echo $ {# ARRAY} # imprimeuri 3 - lungimea tabloului?
Cu toate acestea, dacă modificăm puțin exemplul, se pare că se rupe:

 ARRAY = (abc)
 ecou $ {# ARRAY} # imprimeuri 1

Acest lucru se datorează faptului că ${#ARRAY}este același ${#ARRAY[0]}, care contează numărul de caractere din primul element a,.

Este posibil să numărați numărul elementelor din tablă, dar tabloul trebuie specificat explicit cu @:

 ARRAY = (abc)
 ecou $ {# ARRAY [@]} # imprimeuri 3
De asemenea, este posibil să tăiați șiruri și tablouri:

 string = "Sunt un fan al câinilor".
 echo $ {string: 6: 3} # fan tipărește

 array = (abcdefghij)
 echo $ {array [@]: 3: 2} # imprimeuri de
Testarea existenței
Unele operații testează dacă variabila este setată:

 nume de utilizator nesetat
 echo $ {username-default} # imprime implicit

 Nume de utilizator admin =
 echo $ {username-default} # imprime admin
Pentru operațiunile care testează dacă o variabi
lă este setată, pot fi obligate să verifice dacă variabila este setată și nu este golă prin adăugarea unui punct (" :"):

 nesimțit foo
 bara nesetată

 ecou $ {foo-abc} # imprimeuri abc
 echo $ {bar: -xyz} # print xyz

 foo = ""
 bar = ""

 echo $ {foo-123} # tipărește nimic
 echo $ {bar: -456} # imprimeuri 456

Operatorul =(sau :=) este ca și operatorul -, cu excepția faptului că stabilește și variabila dacă nu are nicio valoare:

 cache-ul nesetat
 echo $ {cache: = 1024} # imprimeuri 1024
 echo $ cache # imprimeuri 1024

 echo $ {cache: = 2048} # imprimeuri 1024
 echo $ cache # imprimeuri 1024
+Operatorul dă valoarea dacă variabila este setată, și nimic altceva:

 nesimțit foo
 bara nesetată

 foo = 30

 ecou $ {foo + 42} # imprimeuri 42
 echo $ {bar + 1701} # tipărește nimic
Operatorul ?blochează programul cu mesajul specificat dacă variabila nu este setată:

  : $ {1? Eșec: niciun argument}} blocă programul dacă nu există primul argument
( :Comanda ignoră toate argumentele sale și este echivalentă cu true.)

Privire indirectă
Bash permite căutare indirectă a variabilei / a tabloului cu !operatorul prefixului.

Adică se comportă ca și dacă numai asta a funcționat: ${!expr}${${expr}}

 foo = bar
 bar = 42
 
 ecou $ {! foo} # tipărește $ bar, care este 42

 alpha = (abcdefghijklmnopqrstu vwxyz)
 char = alpha [12]

 ecou $ {! char} # tipărește $ {alpha [12]}, care este m
Array quirks: * versus @
Există două variabile speciale suplimentare: $*și [email protected]

[Toate comportamentele descrise în această secțiune se aplică tablourilor atunci când sunt accesate prin intermediul sau de asemenea.] ${array[*]}${array[@]}

Ambele par să conțină argumentele transmise scriptului / procedurii curente, dar au un comportament subtil diferit atunci când sunt citate:

Pentru a ilustra diferența, trebuie să creăm câteva scripturi de ajutor.

În primul rând, creați print12:

#! / Bin / bash                                                                     
# tipărește primul parametru, apoi al doilea:
ecou "primul: $ 1"
ecou "secundă: $ 2"
Apoi, creați showargs:

#! / Bin / bash
 
ecou $ *
ecou $ @

ecou „$ *”
ecou „$ @”

bash print12 "$ *"
bash print12 "$ @"

Acum, executați showargs:

 $ bash showargs 0 "1 2 3"
la imprimare:

0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3
întâi: 0 1 2 3
al doilea: 
primul: 0
al doilea: 1 2 3

Acest lucru se întâmplă deoarece "$*"combină toate argumentele într-un singur șir, în timp ce "[email protected]"necesită argumente individuale.

Există o altă diferență subtilă între cele două: dacă variabila IFS(separator de câmp intern) este setată, atunci conținutul acestei variabile este împărțit între elementele din "$*".

Creați un script numit atvstar:

#! / Bin / bash

IFS = ""

ecou $ *
ecou $ @

ecou „$ *”
ecou „$ @”
Și executați-l:

 $ bash atvstar 1 2 3 
la imprimare:

1 2 3
1 2 3
1,2,3
1 2 3
IFS trebuie să conțină un singur caracter.

Din nou, aceste aceleași comportamente de citare se transferă în tablouri atunci când sunt subscrise cu *sau @:

 arr = ("a b" "cd e")

 echo $ {arr [*]} # imprimeuri abcde
 ecou $ {arr [@]} # imprimeuri abcde

 ecou „$ {arr [*]}” # imprimeuri abcde
 ecou „$ {arr [@]}” # imprimeuri abcde

 bash print12 "$ {arr [*]}"  
 # amprente:
 # primul: abcde
 # al doilea:

 bash print12 "$ {arr [@]}"
 # amprente:
 # primul: ab
 # al doilea: cde
Corzi și cotare
Șirurile în bash sunt secvențe de caractere.

Pentru a crea un șir literal, utilizați ghilimele unice; pentru a crea un șir interpolat, utilizați ghilimele duble:

 Lume = Pământ
 foo = 'Bună ziua, lume $!'
 bar = "Bună ziua, lume $!"
 ecou $ foo # imprimeuri Bună ziua, lume $!
 ecou $ bar # imprimeuri Bună, Pământ!
În șirurile intepolate, variabilele sunt convertite la valorile lor.

domeniu
În bash, domeniul de aplicare variabil este la nivelul proceselor: fiecare proces are propria copie a tuturor variabilelor.

În plus, variabilele trebuie marcate pentru exportul în procesele copil:

 foo = 42

 bash somescript # somescript nu poate vedea foo

 export foo

 bash somescript # somescript poate vedea foo

 ecou "foo =" $ foo # tipărește întotdeauna foo = 42
Să presupunem că acesta este somescript:

#! / Bin / bash
ecou "vechi foo = $ foo"
foo = 300
ecou "new foo = $ foo"
Ieșirea din cod ar fi:

foo veche = 
foo nou = 300
foo veche = 42
foo nou = 300
foo = 42
Expresii și aritmetică
Este posibil să scrieți expresii aritmetice în bash, dar cu o anumită prudență.

Comanda exprtipărește rezultatul expresiilor aritmetice, dar trebuie să aveți grijă:

 expr 3 + 12 # imprimeuri 15
 expr 3 * 12 # (probabil) se prăbușește: * se extinde la toate fișierele 
 expr 3 \ * 12 # imprimeuri 36
Notația de atribuire este mai iertator: (( assignable = expression ))
((x = 3 + 12)); ecou $ x # imprimeuri 15
 ((x = 3 * 12)); ecou $ x # imprimeuri 36
Dacă doriți rezultatul unei expresii aritmetice fără atribuirea acesteia, puteți utiliza : $((expression))

 ecou $ ((3 + 12)) # imprimeuri 15
 ecou $ ((3 * 12)) # imprimeuri 36
În timp ce declararea variabilelor implicit este norma în bash, este posibil să se declare explicit variabile și să se atașeze un tip la ele.

Formularul creează o variabilă întreagă explicită: declare -i variable

 declara numarul -i
 număr = 2 + 4 * 10
 ecou numărul $ # imprimeuri 42

 alt = 2 + 4 * 10
 ecou $ alt # imprimeuri 2 + 4 * 10

 număr = "foobar"
 ecou numărul $ # imprimeuri 0
Atribuirile pentru variabile întregi vor forța evaluarea expresiilor.

Fișiere și redirecționare
Fiecare proces din Unix are acces la trei canale de intrare / ieșire în mod implicit: STDIN (intrare standard), STDOUT (ieșire standard) și STDERR (eroare standard).

Când scrieți în STDOUT, ieșirea apare (implicit) la consolă.

Când citiți de la STDIN, acesta citește (implicit) direct din ceea ce utilizatorul introduce în consolă.

Când scrieți în STDERR, ieșirea apare (implicit) la consolă.

Toate aceste canale pot fi redirecționate.

De exemplu, pentru a descărca conținutul unui fișier în STDIN (în loc să accepte introducerea utilizatorului), utilizați <operatorul:

 # tipărește linii în fișier care conțin cuvântul foo:
 grep foo <myfile 
Pentru a descărca ieșirea unei comenzi într-un fișier, utilizați >operatorul:

 # concatenează fișier1 cu fișier2 în fișier nou combinat:
 cat file1 file2> combinat 
Pentru a adăuga la sfârșitul unui fișier, utilizați >>operatorul:

 # scrie data și ora curente până la sfârșitul unui fișier numit jurnal:
 data >> jurnal
Pentru a specifica conținutul STDIN literal, într-un script, utilizați notația: <<endmarker

pisica << ÎNAINTE
Toate acestea vor fi tipărite.

Deoarece toate acestea intră în pisică pe STDIN.

UNTILHERE
Totul până la următoarea instanță de endmarkerla sine pe o linie este redirecționat către STDIN.

Pentru a redirecționa ieșirea de eroare (STDERR), utilizați operatorul 2>:

 # scrie erori de la pornirea demonului web la un jurnal de erori:
 httpd 2> eroare.log
De fapt, toate canalele I / O sunt numerotate, și >este aceeași ca și 1>.

STDIN este canalul 0, STDOUT este canalul 1, în timp ce STDERR este canalul 2.

Notația redirecționează ieșirea canalului M la canalul N . M>&N

Deci, este simplu să afișăm erori pe STDOUT:

 grep foo nofile 2> & 1 # erori vor apărea pe STDOUT
Captarea STDOUT cu backquotes
Există o altă formă citând în bash care arata ca un șir de caractere - backtick: ``.

Aceste ghilimele execută comenzile din interiorul lor și renunță la ieșirea procesului în loc:

 # scrie data și utilizatorul în jurnal:
 ecou `data`` whoami` >> jurnal  

Având în vedere că uneori este utilă pentru a cuibări aceste extinderi, cochilii mai noi au adăugat o notație nestabilă : $(command)

 # scrie data și utilizatorul în jurnal:
 ecou $ (data) $ (whoami) >> jurnal  
Este tentant să importăm conținutul unui fișier , dar există o scurtătură simplă încorporată :`cat path-to-file``<path-to-file`

 echo user: `<config / USER` # tipărește conținutul config / USER
Redirecționare cu exec

Comanda specială bash execpoate manipula canalele peste game de comenzi:

 exec <file # STDIN a devenit fișier
 exec> fișierul # STDOUT a devenit fișier

Poate doriți să salvați STDIN și STDOUT pentru a le restabili ulterior:

 exec 7 <& 0 # STDIN salvat ca canal 7
 exec 6> & 1 # STDOUT salvat ca canal 6

Dacă doriți să înregistrați toate ieșirile dintr-un segment de script, puteți combina acestea împreună:

 exec 6> & 1 # STDOUT salvat ca canal 6
 exec> LOGFILE # toate rezultatele ulterioare se duc la LOGFILE

 # pune comenzile aici

 exec 1> & 6 # restaurează STDOUT; ieșire la consolă din nou
Țevi
De asemenea, este posibil să rutați STDOUT-ul unui proces către STDIN-ul altuia folosind |operatorul (conductă):

 # tipărește intrarea root în baza de date cu parola utilizatorului:
 pisică / etc / passwd | rădăcină grep
Forma generală a operatorului de conducte este:

 ieșire-comandă | inputing-comandă
Și, este posibilă încadrarea comenzilor în „conducte”:

 # Un singur liner pentru a găsi porți spațiale în directorul curent:

 # du-rachete * # tipărește utilizarea spațiului
              numărul de fișiere din directorul curent

 # sort -rn # sorts STDIN, numeric,
              # de prima coloană în ordine inversă

 # head # tipărește primele 10 intrări de la STDIN

 du-rachete * | sort -rn | cap
Unele programe acceptă un nume de fișier din care să citească în loc să citească de la STDIN.

Pentru aceste programe sau programe care acceptă mai multe nume de fișiere, există o modalitate de a crea un fișier temporar care conține ieșirea unei comenzi, formularul. <(command)

Expresia se extinde în numele unui fișier temporar care conține ieșirea de rulare . <(command)command

Aceasta se numește substituirea procesului.

 # adaugă uptime, data și ultima linie de eveniment.log pe main.log:
 pisica <(uptime) <(data) <(coada -1 eveniment.log) >> main.log

procese
Bash excelează la procesele de coordonare.

Conductele acționează pentru a coordona mai multe procese împreună.

De asemenea, este posibil să rulați procesele în paralel.

Pentru a executa o comandă în fundal, utilizați & operatorul postfix:

 timp consumator de timp &
Și, pentru a obține id-ul procesului, utilizați $!variabila specială imediat după nașterea procesului:

 timp consumator de timp &
 pid = $!
Cele mai waitasteapta comanda pentru proces asociat unui proces de id pentru a termina:

 timp consumator de timp &
 pid = $!
 asteapta $ pid
 proces ecou $ pid terminat.

Fără un cod de proces, waitașteaptă ca toate procesele copilului să se termine.

Pentru a converti un folder de imagini din JPG în PNG în paralel:

pentru f în * .jpg
do 
  convertiți $ f $ {f% .jpg} .png &
Terminat 
aștepta
ecou Toate imaginile au fost convertite.
Globuri și modele

Bash furnizează utilizarea notării glob pentru a se potrivi pe șiruri și nume de fișiere.

În majoritatea contextelor din bash, un model glob se extinde automat la o serie de nume de fișiere potrivite:

 echo * .txt # tipărește numele tuturor fișierelor text
 echo *. {jpg, jpeg} # tipărește numele tuturor fișierelor JPEG

Modelele glob au mai multe forme speciale:

* se potrivește cu orice șir.
? se potrivește cu un singur personaj.
[chars]se potrivește cu orice personaj din chars.
[a-b]se potrivește cu orice personaj între ași b.
Folosind aceste tipare, este ușor să eliminați toate fișierele formularului , unde este un număr de 3 cifre: fileNNNNNN

 fișier rm [0-9] [0-9] [0-9]
Forma creată „set” cret pare să acționeze ca un model, dar se va extinde chiar dacă fișierele nu există: se extinde la sau sau ... {string1,string2,...,stringN}string1string2

Este posibil să se creeze o "bombă bash": un model care crește exponențial ca dimensiune sub expansiune:

 ecou {0,1} # imprimeuri 0 1

 ecou {0,1} {0,1} # imprimeuri 00 01 10 11

 ecou {0,1} {0,1} {0,1} # imprimeuri 000 001 010 011 100 101 110 111
Structuri de control

La fel ca majoritatea limbilor, bash acceptă structuri de control pentru condiționări, iterație și subrutine.

Condiționalele
Dacă există alte condiții, în bash, ca în alte limbi.

Cu toate acestea, în bash condiția este o comandă, iar o stare de ieșire a succesului (0) este „true”, în timp ce o stare de ieșire a eșecului (non-zero) este „falsă”:

# aceasta va tipări:
daca e adevarat
atunci  
  ecou tipărit
Fi 

# aceasta nu va tipări:
dacă este fals
atunci  
  ecou neimprimat
Fi 

Bash poate întreprinde diferite acțiuni cu privire la succesul sau eșecul unui program:

dacă httpd -k începe
atunci
  ecou "httpd a început OK"
altfel
  ecou "httpd nu a reușit să înceapă"
Fi
În bash, multe condiții sunt construite din comanda specială test.

Testul de comandă necesită multe stegulețe pentru a efectua teste condiționate.

Fugiți help testsă le enumerați pe toate.

Unele steaguri populare includ:

-e file este adevărat dacă există un fișier / director specific.
-z string este adevărat dacă șirul dat este gol.
string1 = string2 este adevărat dacă cele două șiruri sunt egale.
Există o notație alternativă pentru utilizarea paranteze pătrate: . test args[ args ]

Condiționalele pot verifica dacă argumentele au semnificație:

 dacă ["$ 1" = "-v"]
 atunci
   ecou „trecerea la ieșirea verboasă”
   VERBOSE = 1
 Fi
Repetare

Forma execută până când testul comanda se completează cu starea de iesire nenulă: while command; do commands; donecommands

 # reporni automat httpd-ul în cazul în care se blochează:
 în timp ce adevărat
 do
    httpd
 Terminat

Este posibil să iterați elementele dintr-un tablou cu o buclă: for var in array; do commands; done

 # compila toate fișierele c dintr-un director în binare:
 pentru f în * .c
 do
   gcc -o $ {f% .c} $ f
 Terminat
subrutine

Subrutinele Bash sunt ca niște scripturi separate.

Există două sintaxe pentru definirea unei subrutine:

nume funcție {
   comenzi
}
și:

nume () {
   comenzi
}

După ce a declarat, o funcție acționează aproape ca un script separat: argumente pentru funcția de vin ca pentru n - lea argument. $n

O diferență majoră este că funcțiile pot vedea și modifica variabile definite în scriptul exterior:

count = 20

funcție showcount {
  ecou $ count
  count = 30
}

showcount # imprimeuri 20

echo $ count # printuri 30


Exemple


Îmbunătățirea acestui lucru ne permite să scriem programe în bash.

Iată o subrutină pentru calcularea factorială:

fapt funcție {
  rezultat = 1
  n = $ 1
  în timp ce ["$ n" -gege 1]
  do
    rezultat = $ (expr $ n \ * $ rezultat)
    n = $ (expr $ n - 1)
  Terminat
  ecou rezultat $
}
Sau, cu notarea expresiei:

function facter {
  rezultat = 1
  n = $ 1
  while ((n> = 1))
  do
    ((rezultat = n * rezultat))
    ((n = n - 1))
  Terminat
  ecou rezultat $
}
Sau, cu variabile întregi declarate:

factered () {
  declara-i rezultat
  declară -in

  n = $ 1
  rezultat = 1

  while ((n> = 1))
  do
    Rezultatul = n * rezultat
    n = n-1
  Terminat

  ecou rezultat $
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  


×