Shell-skript er mye brukt i UNIX-verdenen. De er gode for å øke gjentatte oppgaver og forenkle komplekse utførelseslogikk. De kan være like enkle som et sett med kommandoer, eller de kan orkestrere komplekse oppgaver. I denne opplæringen lærer vi mer om Bashs skriptspråk ved å skrive et eksempelskript trinn for trinn.
En av de beste måtene å lære om et nytt språk er ved eksempel. La oss starte med en.
Fizz-Buzz-problemet er en veldig enkel. Det ble kjent etter en programmerer, kalt Imran, brukt den som en intervju test. Det viser seg at 90-99,5% av kandidatene til en programmeringsjobb bare ikke kan skrive det enkleste programmet. Imran tok dette enkle Fizz-Buzz-spillet og ba kandidatene om å løse det. Mange fulgte Imrans eksempel, og i dag er det et av de mest stilte vanlige spørsmålene til en programmeringsjobb. Hvis du ansetter, og trenger en måte å filtrere gjennom 90% av kandidatene, er dette et godt problem å presentere.
Her er reglene:
Det er alt der er til det. Jeg er sikker på at de fleste av dere allerede kan visualisere de to eller tre hvis
uttalelser for å løse dette. La oss jobbe gjennom dette ved hjelp av Bashs skriptspråk.
En shebang refererer til kombinasjonen av hash og utropstegn tegn: #!
. Programlaster vil se etter en shebang på første linje i skriptet, og bruk tolken som er angitt i den. En shebang består av følgende syntaks: #!tolk [parametere]
. Tolken er det programmet som brukes til å tolke vårt språk. For bash scripting, ville det være / Bin / bash
. For eksempel, hvis du vil lage et skript i PHP og kjøre det i konsoll, vil du sikkert bruke / Usr / bin / php
(eller banen til PHP-kjørbar på maskinen din) som tolk.
#! / Usr / bin / phpJa, det vil faktisk fungere! Er det ikke enkelt? Bare vær sikker på å gjøre filen kjørbar først. Når du gjør dette, vil dette skriptet sende ut PHP-informasjonen som du forventer.
Tips: For å sikre at skriptet ditt fungerer på så mange systemer som mulig, kan du bruke
/ Bin / env
i shebang. Som sådan, i stedet for/ Bin / bash
, du kan bruke/ bin / env bash
, som vil fungere på systemer der bash executable ikke er innenfor/ bin
.
Skrive ut tekst
Utgangen av et skript vil være lik, som du kanskje forventer, hva som kommer ut av kommandoen din. Men hvis vi eksplisitt vil skrive noe på skjermen, kan vi bruke
ekko
.#! / bin / bash echo "Hello World"Kjører dette skriptet vil skrive ut "Hello World" i konsollen.
csaba @ csaba ~ $ ./helloWorld.sh Hello World csaba @ csaba ~ $
Vi presenterer variabler
Som med alle programmeringsspråk, kan du bruke variabler når du skriver shell-skript.
#! / bin / bash message = "Hello World" ekko $ meldingDenne koden gir nøyaktig samme "Hello World" -melding. Som du kan se, for å tilordne en verdi til en variabel, skriv bare navnet sitt - ekskluder dollarskiltet foran den. Vær også forsiktig med mellomrom; Det kan ikke være noen mellomrom mellom variabelnavnet og likestegnet. Så
melding = "Hei"
i stedet formelding = 'Hei'
Når du ønsker å bruke en variabel, kan du ta verdien av den, akkurat som vi gjorde i
ekko
kommando. Forbereder en$
til variabelenes navn returnerer verdien sin.Tips: Semikoloner er ikke nødvendig i bash scripting. Du kan bruke dem i de fleste tilfeller, men vær forsiktig: de kan ha en annen mening enn det du forventer.
Skrive ut tallene mellom 1 og 100
Fortsett med vårt demo-prosjekt, vi trenger å sykle gjennom alle tallene mellom 1 og 100. For dette må vi bruke en
til
sløyfe.#! / bin / bash for nummer i 1 ... 100; gjør ekko $ nummer gjortDet er flere nye ting verdt å merke seg i dette eksemplet - som forresten skriver ut alle tallene fra 1 til 100, ett tall om gangen.
til
syntaks i Bash er: for VARIABLE i RANGE; Gjør COMMAND ferdig
.1 ... 100
inn i et utvalg i vårt eksempel. De brukes også i andre sammenhenger, som vi snart vil se gjennom.gjøre
og til
er egentlig to separate kommandoer. Hvis du vil plassere to kommandoer på en enkelt linje, må du skille dem på en eller annen måte. En måte er å bruke semikolon. Alternativt kan du skrive koden uten en semikolon ved å flytte gjøre
til den følgende linjen.#! / bin / bash for nummer i 1 ... 100 gjør ekko $ nummer gjort
Nå som vi vet hvordan du skriver ut tallene mellom 1 og 100, er det på tide å ta vår første beslutning.
#! / bin / bash for nummer i 1 ... 100; gjør hvis [$ ((tall% 3)) -eq 0]; deretter ekko "Fizz" ellers ekko $ nummer fi gjort
Dette eksemplet vil utgjøre "Fizz" for tall delbart med 3. Igjen må vi takle litt ny syntaks. La oss ta dem en etter en.
hvis ... da ... annet ... fi
- dette er den klassiske syntaksen for en hvis
uttalelse i Bash. Selvfølgelig, den ellers
del er valgfritt - men nødvendig for vår logikk i dette tilfellet.hvis COMMAND-RETURN-VALUE; deretter…
- hvis
vil utføre hvis returverdien av kommandoen er null. Ja, logikken i Bash er null basert, noe som betyr at kommandoer som utføres, avslutter med en kode på 0. Hvis noe går galt, vil et positivt heltall bli returnert. For å forenkle ting: Alt annet enn 0 er vurdert falsk
.$ ((Nummer% 3))
vil returnere gjenværende verdi for å dividere variabelen, Nummer
, ved 3. Vær oppmerksom på at vi ikke brukte $
inne i parentesen - bare foran dem.Du lurer kanskje på hvor kommandoen er i vårt eksempel. Er det ikke bare en brakett med et merkelig uttrykk i det? Vel, det viser seg det [
er faktisk en kjørbar kommando. For å leke med dette, kan du prøve følgende kommandoer i konsollen.
csaba @ csaba ~ $ som [/ usr / bin / [csaba @ csaba ~ $ [0-eq 1] csaba @ csaba ~ $ echo $? 1 csaba @ csaba ~ $ [0 -eq 0] csaba @ csaba ~ $ echo $? 0
Tips: En kommandos utgangsverdi blir alltid returnert til variabelen,
?
(spørsmålstegn). Det overskrives etter hver ny kommandos kjøring.
Vi har det bra så langt. Vi har "Fizz"; nå la oss gjøre "Buzz" -delen.
#! / bin / bash for nummer i 1 ... 100; gjør hvis [$ ((tall% 3)) -eq 0]; deretter ekko "Fizz" elif [$ ((tall% 5)) -eq 0]; deretter ekko "Buzz" ellers ekko $ nummer fi gjort
Ovenfor har vi introdusert en annen betingelse for delbarhet med 5: elif
uttalelse. Dette, selvfølgelig, oversetter til eller hvis, og vil bli utført hvis kommandoen som følger med den returnerer ekte
(eller 0
). Som du kan observere, de betingede uttalelsene i []
er vanligvis evaluert ved hjelp av parametere, for eksempel -ekv
, som står for "likestiller".
For syntaksen,
arg1 OP arg2
,OP
er en av-ekv
,-ne
,-lt
,-le
,-gt
, eller-ge
. Disse aritmetiske binære operatørene returnererekte
hvisarg1
er lik, ikke lik, mindre enn, mindre enn eller lik, større enn eller høyere enn eller likarg2
, henholdsvis.arg1
ogarg2
kan være positive eller negative heltall. - Bash Manual
Når du prøver å sammenligne strenger, kan du bruke den kjente ==
signere, eller til og med et enkelt like tegn vil gjøre. !=
avkastning ekte
når strengene er forskjellige.
Så langt kjører koden, men logikken er ikke riktig. Når nummeret er delbart med både 3 og 5, vil vår logikk ekko bare "Fizz". La oss endre vår kode for å tilfredsstille det siste kravet til FizzBuzz.
#! / bin / bash for nummer i 1 ... 100; gjør hvis [$ ((tall% 3)) -eq 0]; deretter output = "Fizz" fi hvis [$ ((tall% 5)) -eq 0]; så output = "$ output Buzz" fi hvis [-z $ output]; da ekko $ nummer annet ekko $ output; fi gjort
Igjen har vi fått gjøre en håndfull endringer. Den mest bemerkelsesverdige er introduksjonen av en variabel, og deretter sammenkoblingen av "Buzz" til den, om nødvendig. Strenge i bash er vanligvis definert mellom dobbelte anførselstegn ("). Enkelte anførselstegn kan også brukes, men for enklere sammenkobling er dobbeltrom det bedre valget. Innenfor disse dobbelte sitatene kan du referere til variabler: litt tekst $ variabel annen tekst
"vil erstatte $ variabel
med innholdet. Når du vil sammenkoble variabler med strenger uten mellomrom mellom dem, kan du foretrekke å sette variabelenes navn i krøllete bånd. I de fleste tilfeller, som PHP, er du ikke pålagt å gjøre det, men det hjelper mye når det gjelder kodens lesbarhet.
Tips: Du kan ikke sammenligne tomme stenger. Det ville returnere en manglende parameter.
Fordi argumenter inni []
behandles som parametere, for "["
, de må være forskjellige fra en tom streng. Så dette uttrykket, selv om det er logisk, vil sende ut en feil: [$ output! = ""]
. Det er derfor vi har brukt [-z $ utgang]
, som returnerer ekte
hvis strengen har en lengde på null.
En måte å forbedre vårt eksempel på er å trekke ut i funksjoner det matematiske uttrykket fra hvis
uttalelser, slik som:
#! / bin / bash-funksjonen erDivisibleBy return $ (($ 1% $ 2)) for nummer i 1 ... 100; gjør hvis erDivisibleBy $ nummer 3; så output = "Fizz" fi hvis erDivisibleBy $ nummer 5; så output = "$ output Buzz" fi hvis [-z $ output]; da ekko $ nummer annet ekko $ output; fi gjort
Vi tok uttrykkene som sammenlignet resten med null, og flyttet dem til en funksjon. Enda eliminerte vi sammenligningen med null, fordi null betyr sant for oss. Vi må bare returnere verdien fra det matematiske uttrykket - veldig enkelt!
Tips: En funksjonens definisjon må foregå for å ringe.
I Bash kan du definere en metode som funksjon func_name kommandoer;
. Eventuelt finnes det en andre syntaks for å deklarere funksjoner: func_name () kommandoer;
. Så, vi kan slippe strengen, funksjon
og legg til "()"
etter navnet sitt. Jeg personlig foretrekker dette alternativet, som eksemplifisert i eksemplet ovenfor. Det er mer eksplisitt og ligner på tradisjonelle programmeringsspråk.
Du trenger ikke å angi parametrene for en funksjon i Bash. Sender parametere til en funksjon oppnås ved å bare oppregne over dem etter at funksjonssamtalen er adskilt av hvite mellomrom. Ikke legg kommater eller parentes i funksjonsanropet - det virker ikke.
Mottatte parametere blir automatisk tilordnet variabler etter nummer. Den første parameteren går til $ 1
, den andre til $ 2
, og så videre. Den spesielle variabelen, $ 0
henviser det nåværende skriptets filnavn.
#! / bin / bash funksjon exampleFunc echo $ 1 echo $ 0 IFS = "X" ekko "$ @" ekko "$ *" exampleFunc "one" "two" "three"
Denne koden vil produsere følgende utgang:
csaba @ csaba ~ $ ./parametersExamples.sh one ./parametersExamples.sh one two thre oneXtwoXthre
La oss analysere kilden, linje for linje.
$ @
. Den representerer alle parametrene som et enkelt ord, akkurat som angitt i funksjonssamtalen.$ *
. Den representerer alle parametrene, tatt en-for-en og sammenkalt med første bokstav i IFS-variabelen. Derfor er resultatet oneXtwoXthre
.Som nevnt tidligere, kan funksjoner i Bash bare returnere heltall. Som sådan skriver du returnere "en streng"
ville være ugyldig kode. Likevel, i mange situasjoner, trenger du mer enn bare en null eller en. Vi kan refactor vårt FizzBuzz eksempel slik at i til
uttalelse, vi skal bare ringe et funksjonsanrop.
#! / bin / bash-funksjonen erDivisibleBy return $ (($ 1% $ 2)) funksjon fizzOrBuzz if isDivisibleBy $ 1 3; så output = "Fizz" fi hvis erDivisibleBy $ 1 5; så output = "$ output Buzz" fi hvis [-z $ output]; da ekko $ 1 annet ekko $ output; fi for nummer i 1 ... 100; gjør fizzOrBuzz $ nummer gjort
Vel, dette er det første trinnet. Vi har nettopp hentet hele koden til en funksjon, kalt fizzOrBuzz
, og deretter erstattet $ nummer
med $ 1
. Imidlertid skjer all utmatning i fizzOrBuzz
funksjon. Vi ønsker å sende ut fra til
loop med en ekko
setning, slik at vi kan prepend hver linje med en annen streng. Vi må fange fizzOrBuzz
funksjonens utgang.
# [...] for nummer i 1 ... 100; gjør ekko "-'fizzOrBuzz $ nummer '" fizzBuzzer = $ (fizzOrBuzz $ nummer) ekko "- $ fizzBuzzer" gjort
Vi har oppdatert vår til
loop bare litt (ingen andre endringer). Vi har nå egget alt to ganger på to forskjellige måter for å eksemplifisere forskjellene mellom de to løsningene til det samme problemet.
Den første løsningen for å fange utgangen av en funksjon eller en annen kommando er å bruke backticks. I 99% av tilfellene vil dette fungere helt fint. Du kan bare referere til en variabel innenfor backticks etter navnene deres, som vi gjorde med $ nummer
. De første linjene i utgangen bør nå se ut som:
csaba @ csaba ~ / Personal / Programming / NetTuts / Grunnleggende om BASH Scripting / Kilder $ ./fizzBuzz.sh -1 -1 -2 -2 -Fizz -Fizz -4 -4 -Buzz -Buzz -Fizz -Fizz -7 -7
Som du kan se, blir alt duplisert. Samme utgang.
For den andre løsningen har vi valgt å først tildele returverdi til en variabel. I den oppgaven brukte vi $ ()
, som i dette tilfellet forgir skriptet, kjører koden og returnerer sin utgang.
Husker du at vi brukte semikolon her og der? De kan brukes til å utføre flere kommandoer skrevet på samme linje. Hvis du skiller dem fra semikolon, blir de rett og slett henrettet.
Et mer sofistikert tilfelle er å bruke &&
mellom to kommandoer. Ja, det er en logisk AND; det betyr at den andre kommandoen vil bli utført bare hvis den første kommer tilbake ekte
(det går ut med 0). Dette er nyttig; vi kan forenkle hvis
uttalelser i disse kortene:
#! / bin / bash-funksjonen erDivisibleBy return $ ($ 1% $ 2)) funksjon fizzOrBuzz isDivisibleBy $ 1 3 && output = "Fizz" erDivisibleBy $ 1 5 && output = "$ output Buzz" hvis [-z $ utgang ]; da ekko $ 1 annet ekko $ output; fi for nummer i 1 ... 100; gjør ekko "-'fizzOrBuzz $ nummer '" ferdig
Som vår funksjon, isDivisibleBy
returnerer en riktig returverdi, vi kan da bruke &&
å angi variabelen vi ønsker. Hva er etter? &&
vil bli utført bare hvis tilstanden er ekte
. På samme måte kan vi bruke ||
(dobbeltrørskarakter) som en logisk ELLER. Her er et raskt eksempel nedenfor.
csaba @ csaba ~ $ echo "bubu" || ekko "bibi" bubu csaba @ csaba ~ $ echo false || ekko "bibi" false csaba @ csaba ~ $
Så det gjør det for denne opplæringen! Jeg håper at du har plukket opp en håndfull nye tips og teknikker for å skrive dine egne Bash-skript. Takk for at du leser, og hold deg oppdatert for mer avanserte artikler om dette emnet.