Een eenvoudige handleiding voor Linux shell scripting met Bash

Ben je ooit in de situatie geweest dat je meer wilde leren over Linux shell scripting, maar je wist niet waar je moest beginnen? Ben je relatief nieuw in de wereld van op Unix-gebaseerde besturingssystemen en wil je je vaardigheden uitbreiden om wat basis shell programmering te doen? Deze tutorial voor beginners zal de basisprincipes van Linux shell scripting met Bash behandelen, inclusief het maken en uitvoeren van een script, evenals werken met strings en loops.

Shell scripting wordt gebruikt om veelvoorkomende administratieve taken te automatiseren

Ongeacht het besturingssysteem worden shell scripts gebruikt om repetitieve administratieve taken te automatiseren. Bijvoorbeeld, in Windows kun je bestanden hernoemen met behulp van de Verkenner. Maar als je veel bestanden moet hernoemen, zou het een tijdrovende taak zijn om de grafische shell te gebruiken. PowerShell stelt je in staat om de taak te automatiseren en betrouwbaar te herhalen.

Advertentie

In op Unix-gebaseerde besturingssystemen worden Bash en andere shells gebruikt om taken te automatiseren zoals werken met bestanden, systeemconfiguratie aanpassen, en vele andere taken die anders zouden kunnen worden uitgevoerd door enkele commando’s in te typen.

Wat je nodig hebt om Bash shell scripting te leren

Om een Bash script te schrijven en uit te voeren, heb je slechts drie dingen nodig:

  • Elk teksteditor zoals bijvoorbeeld Kladblok, Teksteditor, TextEdit, vi, emacs of Visual Studio Code.
  • terminal emulator, an application that comes preinstalled with most operating systems and is often called Terminal, Console, or Command Prompt.
  • Bash zelf.

De terminalemulator is waar je commando’s typt en uitvoert door op Enter of Return te drukken. Wat betreft Bash, of het al geïnstalleerd is, hangt af van je platform:

  • Op macOS is Bash standaard geïnstalleerd. Op recentere versies is de Z-shell (zsh) de standaard shell, en dat is ook goed. Zolang Bash geïnstalleerd is, kun je Bash-scripts ook vanuit zsh uitvoeren.
  • Linux distributies hebben meestal Bash geïnstalleerd. (Je kunt controleren door te kijken of je systeem het bestand /bin/bash bevat.) Android is een bijzonder geval dat geen Bash meebrengt. Er zijn stappen om Bash op Android te krijgen, waar dit artikel niet op in gaat.
  • Windows wordt niet standaard geleverd met Bash. PowerShell is de standaard opdrachtregelshell in Windows. Je moet een Linux distributie installeren onder de Windows Subsystem voor Linux (WSL) om Bash uit te voeren.

Om je Bash-versie te vinden, voer je het bash –version commando uit. Hoewel zelfs oudere Bash-versies je veel kracht geven, introduceren Bash 3 en 4 beiden mooie verkorte notaties voor bepaalde basiscommando’s. Als een commando een van deze Bash-versies vereist, wordt dit hieronder vermeld.

Advertentie

Wat is een shell?

In de computerwereld is een shell een programma dat dient als interface voor het onderliggende besturingssysteem. Een shell kan een grafische gebruikersinterface (GUI) zijn, zoals de Windows shell.

Shell-scriptingtalen

Echter gebruiken mensen over het algemeen de term om specifiek te verwijzen naar een commandoregelinterface (CLI) – een interface bestaande uit tekstregels waarmee u alleen met het toetsenbord kunt communiceren. Hier zijn enkele voorbeelden van shell-scripting talen voor *nix-besturingssystemen:

Hier zullen we ons richten op de Bash-shell. Het is een populaire gratis Unix-shell die standaard is geïnstalleerd op de meeste Linux-distro’s en op macOS.

Wat is een shell-script?

Shells hebben hun eigen programmeertaal. U gebruikt deze taal om opdrachten naar de shell te sturen, die deze vervolgens uitvoert. U kunt deze opdrachten direct in de shell typen, of u kunt ze opslaan in een bestand – een script – en dat bestand vervolgens vanuit de shell uitvoeren. De syntaxis voor het schrijven van opdrachten is in beide gevallen hetzelfde.

Advertentie

In dit artikel worden de basisprincipes van shell-scripting behandeld om dit bestand te maken.

Basis shell-scripting

Laten we beginnen met enkele eenvoudige shell-scripting. Om een eenvoudig script te schrijven, zullen we enkele eenvoudige shell-scriptopdrachten leren in Linux:

  1. Maak een nieuw leeg tekstbestand aan in een teksteditor.
  2. Schrijf #!/bin/bash als eerste regel.
  3. Typ daaronder je commando’s.
  4. Sla het bestand op, bij voorkeur met een “.sh” extensie of zonder extensie.

De #!/bin/bash regel wordt een “shebang” genoemd. Het vertelt je shell dat dit script moet worden uitgevoerd in Bash en de eerste regel van je script moet zijn. Als je overschakelt naar een andere shell, wordt je script nog steeds in Bash uitgevoerd.

Om dit proces zelf uit te proberen, maak je een bestand genaamd ‘hello_world’ in je home-directory aan:

#!/bin/bash
echo "hello world"

Dat is alles — je hebt een Bash-script gemaakt!

Our “hello world” script is just a simple text file

Voordat je het kunt uitvoeren, moet je waarschijnlijk de bestandsrechten wijzigen.

Permissies instellen om een shellscript uit te voeren met chmod

Om de permissies op ons ‘hello_world‘ bestand te wijzigen, zou je dit specifieke commando uitvoeren in je terminal emulator. Hiermee krijgt de gebruiker die het bestand bezit toestemming om het bestand uit te voeren.:

chmod u+x 'hello_world'
Running our script without vs. with the “execute” permission

Als je gewoon je shell-script wilt uitvoeren, kun je doorgaan naar de volgende sectie. Voor degenen die nieuwsgierig zijn naar het chmod commando, chmod is een afkorting voor “change mode”, en dient om bestands-“modus” (of rechten) te veranderen in Unix. In Unix-achtige besturingssystemen kun je bestandsrechten instellen voor 3 klassen van gebruikers:

  • De gebruiker die het bestand bezit (vertegenwoordigd door u in chmod).
  • De groep die het bestand bezit (g).
  • Anderen (o).

Met het chmod commando kun je ook a gebruiken om naar al deze te verwijzen.

Elk bestand heeft 3 soorten machtigingen (of “modi”):

  • Lezen (r)
  • Schrijven (w)
  • Uitvoeren (x)

En je kunt ook machtigingen toevoegen (+) of verwijderen (-).

Het eerste parameter in chmod is een combinatie van deze drie — gebruiker eerst, actie tweede, en modus derde. Hier zijn een paar voorbeelden van commando’s:

  • chmod gu+rw 'hello_world' zou lees- en schrijfmachtigingen toevoegen voor de eigenaar en de eigenende groep.
  • chmod a-x 'hello_world' zou uitvoerbare machtigingen verwijderen voor iedereen.
  • chmod u+rwx 'hello_world' 'hello_world_2' zou de eigenaar toestemming geven om de bestanden “hello_world” en “hello_world_2” te lezen, schrijven en uit te voeren.

We hebben hier alleen de basisprincipes van het chmod commando behandeld. Er is ook een meer gecompliceerde, maar minder uitgebreide manier om deze modi te definiëren (de “numerieke notatie”), evenals een ander commando dat je kunt gebruiken om te zien welke machtigingen je bestanden hebben (ls -l). We zullen hier niet verder op ingaan.

Het uitvoeren van een shellscript

Tijd om ons eerste script uit te voeren. Over het algemeen typt u gewoon het pad van het script in de terminal en drukt u op enter.

./hello_world

U kunt het relatieve of het absolute pad gebruiken. Bij gebruik van het relatieve pad, gebruik altijd ./ aan het begin van uw opdracht: Dit vertelt de terminal om in de huidige map te zoeken (voorgesteld door '.'), in plaats van in de mappen die zijn gedefinieerd in de PATH omgevingsvariabele.

Just typing the script name doesn’t work, but running its relative or absolute paths does

Gebruik van opmerkingen om uw script te annoteren

Alles na een # op een enkele regel in een Bash-script wordt beschouwd als een opmerking. Deze kunnen nuttig zijn om te communiceren wat een complexe regel doet of een overzicht te geven van wat grotere delen van uw script doen.

Bijvoorbeeld:

#!/bin/bash

#
# This shell script prints "hello world".
#

echo "hello world" # This line prints "hello world".

Een introductie tot variabelen

Bij het schrijven van scripts kan het handig zijn om variabelen te definiëren. In Bash doe je dit door de variabelennaam en de waarde te typen, gescheiden door een isgelijkteken: VARIABELNAAM='WAARDE'.

Je moet geen spaties naast het isgelijkteken plaatsen — Bash denkt dan dat je een proces wilt uitvoeren.

Gebruik enkele aanhalingstekens om de waarde te omringen om te voorkomen dat Bash het als iets anders interpreteert. In Bash hebben variabelen geen types — alles is in feite een string. Het is aan Bash-programma’s om de string als een ander type te interpreteren, zoals een nummer.

Om de waarde van een variabele te verwijzen, gebruik je de variabelennaam voorafgegaan door het dollarteken: $VARIABELNAAM.

Om dit in de praktijk te proberen, kun je je script wijzigen in:

#!/bin/bash
HELLO="hello variable world"
echo $HELLO # should print "hello variable world"

Argumenten ontvangen

De individuele woorden die je typt bij het invoeren van een opdracht worden argumenten genoemd. In ons voorbeeld chmod u+x 'hello_world'chmodu+x, en 'hello_world' zijn drie verschillende argumenten. chmod is de opdrachtnaam terwijl u+x en hello_world zogeheten parameters zijn — argumenten die extra informatie aan de opdracht geven.

In je script kun je toegang krijgen tot deze argumenten via variabelen. Om conflicten met lokale variabelen te voorkomen, worden deze variabelen genoemd met behulp van nummers — $0 verwijst naar de opdrachtnaam, $1 is het volgende argument dat volgt, $2 het argument daarna, enzovoort.

Laten we dit uitproberen:

#!/bin/bash
HELLO="hello $1 world"
echo $HELLO

Voer nu dit script uit met deze parameters:

./hello_world bash script

De output moet hallo bash wereld zijn, waarbij de eerste parameter gebruikt wordt en de tweede genegeerd.

Als je wilt dat bash script als één parameter wordt gezien, moet je het tussen aanhalingstekens plaatsen: 

./hello_world 'bash script'
Words separated by a space are considered as several arguments, except when in quotes

Het uitvoeren van code conditioneel met behulp van de if-verklaring

Een van de kernzaken die programmeurs willen doen in een script is een stuk code uitvoeren alleen als aan een bepaalde voorwaarde is voldaan. Bash heeft daarvoor de if verklaring:

NUM=$RANDOM
if (( $NUM % 2 )) # if CONDITION
then
    echo "$NUM is odd"
fi # this is how you end an if statement

Tip: Vanaf dit punt worden deze voorbeelden verondersteld deel uit te maken van een groter script en laten we #!/bin/bash aan het begin weg. Vergeet dit echter niet als eerste regel van je script!

Je kunt ook else gebruiken binnen een if verklaring om te specificeren wat te doen als een voorwaarde niet wordt voldaan, of een elif (kort voor “anders als“) verklaring om een andere voorwaarde te specificeren als de eerste voorwaarde niet werd voldaan:

NUM=$RANDOM
if [ $NUM -eq 12 ]
then
    echo "$NUM is my favorite number"
elif (( $NUM % 2 ))
then
    echo "$NUM is odd"
else
    echo "$NUM is even"fi

De ‘fi‘ wordt gebruikt om de if verklaring af te sluiten.

Tip: Als je niet zeker weet hoe je de voorwaarde zelf moet schrijven, kijk dan naar de test, enkele vierkante haken ([]), en dubbele haakjes ((())) notatie.

The output of our script depends on the value of a random variable

Het herhalen van een reeks commando’s met behulp van een for-lus

Nu we hebben behandeld hoe je code voorwaardelijk kunt uitvoeren, laten we eens kijken hoe je code een bepaald aantal keren kunt uitvoeren zolang aan een voorwaarde is voldaan.

De for-lus is perfect voor zo’n taak – met name de “drie-uitdrukking syntaxis”. Het idee erachter is om een ​​lus-specifieke variabele toe te wijzen en deze geleidelijk te veranderen totdat aan een bepaalde voorwaarde is voldaan. Zo is het gestructureerd:

for (( ASSIGNMENT_EXPRESSION ; CONDITION_EXPRESSION ; UPDATE_EXPRESSION ))
do
    COMMANDS
done

Als je bijvoorbeeld wilt dat een lus 10 keer wordt uitgevoerd met waarden voor i die variëren van 0 tot 9, zou je for-lus er zo uit kunnen zien:

for (( i=0; i<10; i++ ))
do
    echo $i
done

Laten we het ontleden:

  • i=0 is the assignment expression here. It’s run only once before the loop is executed, which is why it’s useful for initializing a variable.
  • i<10 is our condition expression. This expression is evaluated before each iteration of a loop. If it is equal to zero (which means the same as “true” in Bash), the next iteration is not run.
  • i++ is our update expression. It’s run after each iteration of a loop.
The structure of our for loop

Door elementen in een lijst te doorlopen

Naast de drie-uitdrukking syntaxis, kun je ook de in sleutelwoord gebruiken om een ​​for-lus te definiëren. Deze alternatieve syntaxis wordt gebruikt om door een reeks items te itereren.

Het meest basale voorbeeld is simpelweg de verzameling items te noemen die je wilt doorlopen na het in-sleutelwoord, gescheiden door spaties. Bijvoorbeeld:

for i in 0 1 2 3 4 5 6 7 8 9 # space-separated list items
do
    echo $i
done

Je kunt ook itereren door items die worden uitvoergegeven door een opdracht:

for i in $(seq 0 1 9)

De $() notatie wordt in het algemeen gebruikt voor opdrachtsubstitutie – het voert een opdracht uit en de uitvoer wordt gebruikt als invoer voor de ouderopdracht eromheen.

Als je door gehele getallen heen wilt itereren, is het beter om de ingebouwde bereiksyntax van Bash te gebruiken, die efficiënter is dan de seq opdracht. Deze syntax is echter alleen beschikbaar in recentere versies van Bash:

  • for i in {0..9}, beschikbaar in Bash 3.
  • for i in {0..9..1}, beschikbaar in Bash 4, waarbij het laatste getal de increment voorstelt.

Op dezelfde manier kun je ook door strings itereren: 

for s in 'item1' 'item2' 'item3'

Het gebruik van globbing om bestanden te verkrijgen die overeenkomen met een patroon

Een van de meest voorkomende use cases voor de for-lussen die besproken zijn in de vorige sectie, is het itereren door individuele bestanden.

Om dit aan te pakken, moeten we eerst zogenaamde “glob-uitbreidingen” behandelen. Dit is een functie in Bash waarmee je bestandsnamen kunt specificeren met behulp van patroonmatching. Er zijn speciale tekens genaamd wildcards die je gebruikt om die patronen te definiëren.

Voordat we hier dieper op ingaan, laten we eens kijken naar een paar specifieke voorbeelden:

  • echo *: Een opdracht die de namen van alle bestanden in uw huidige directory retourneert, behalve verborgen bestanden.
  • echo *.txt: Een opdracht die de namen retourneert van alle niet-verborgen bestanden met een.txt-extensie in uw huidige directory.
  • echo ????: Een opdracht die alle bestandsnamen van vier letters in uw huidige directory retourneert.

De wildcards die we hier hebben gebruikt waren * en ?. Er is nog één wildcard die we niet hebben gebruikt. Hier is een overzicht:

  • De asterisk (*) vertegenwoordigt elk aantal tekens (inclusief 0) in een bestands- of mapnaam.
  • Het vraagteken (?) vertegenwoordigt een enkel teken in een bestands- of mapnaam.
  • De dubbele asterisk (**) vertegenwoordigt elk aantal tekens in een volledig bestandspad. Het is een functie in Bash 4 en hoger en moet worden ingeschakeld door shopt -s globstar uit te voeren.
  • Vierkante haken ([]) worden gebruikt om een teken voor te stellen binnen een reeks symbolen in een bestands- of mapnaam. Bijvoorbeeld [st]ake zou bestanden met de naam sake of take vinden, maar niet stake.

Merk op dat alle verborgen bestanden (bestanden met namen die beginnen met een punt .) worden genegeerd bij het gebruik van glob-uitbreiding.

De vierkante haak-notatie staat iets meer complexiteit toe, zoals:

  • Bereiken bepaald door de eerste en laatste waarde — bijvoorbeeld [1-8]
  • Eliminatie van bepaalde tekens door ! te gebruiken als het eerste teken binnen de haakjes — bijvoorbeeld [!3]

Om één van deze speciale tekens te behandelen als een normaal teken zonder enige betekenis, plaats eenvoudig een backslash ervoor — bijvoorbeeld \?.

A few examples of globbing

Itereren door bestanden met behulp van een for-lus

Nu we de basis van glob-expansie hebben behandeld, laten we eens kijken hoe we het kunnen gebruiken om door bestanden te itereren.

We kunnen eenvoudig de glob-operatoren in de for-lus zelf gebruiken. Hier is een eenvoudig voorbeeld van een lus die de naam van elk bestand in de huidige map afdrukt:

for f in *
do
    echo $f
done

Om de namen van elk bestand in de huidige map en de submappen af te drukken, controleer of je Bash 4.0 of hoger gebruikt door bash --version te draaien, en dan kun je het volgende commando uitvoeren:

shopt -s globstar # enables using **
for f in **
do
    echo $f
done

Tip: Als je een oudere versie van Bash gebruikt, kun je geen gebruik maken van globbing met een for lus hiervoor. Je beste optie zou het find commando zijn, maar dat behandelen we niet in dit artikel.

Dit zijn natuurlijk maar enkele van de eenvoudigste loops die je kunt uitvoeren, maar er is nog veel meer wat je kunt doen. Bijvoorbeeld, om alle JPG’s in een map een consistente opeenvolgende bestandsnaam te geven, zou je het volgende kunnen uitvoeren:

i=1
for f in *.jpg
do
    mv -i -- "$f" "image_$i.jpg"
    let i=i+1
done
Checking the Bash version, then running our script

Code uitvoeren terwijl een voorwaarde waar is

De for loop is niet het enige type loop dat we kunnen gebruiken in Bash – we hebben ook while: Dit type loop wordt uitgevoerd zolang een specifieke voorwaarde waar is.

De syntaxis is vergelijkbaar met de syntaxis van de for loop:

while CONDITION
do
    COMMANDS
done

Voor een praktisch voorbeeld, zo kun je bijvoorbeeld een bestand regel voor regel lezen (zonder voorloopse of nawitruimte) totdat je het einde van het bestand bereikt:

while read -r line
do
    echo "$line"
done < FILENAME # Replace FILENAME with the path to a text file you'd like to read
Using a while loop inside our script to have it print itself

Je kunt ook een for loop vervangen door een while loop, bijvoorbeeld om te itereren van 0 tot 9:

i=0
while [ $i -lt 10 ]
do
    echo $i
    let i=i+1
done

En je zou in theorie ook een loop eindeloos kunnen laten lopen. Hier is een voorbeeld van een commando:

while true
do
    echo "running forever"
done

Tip: Om het script te stoppen, druk gewoon op Ctrl+C.

Hoewel deze oneindige loop op het eerste gezicht nutteloos lijkt, kan het eigenlijk best nuttig zijn, vooral in combinatie met de break statement.

Uit een loop breken

De break statement wordt gebruikt om uit een loop te breken.

Dit stelt je in staat om een oneindige loop uit te voeren en eruit te breken wanneer er breekvoorwaarden optreden.

Om naar een eenvoudig voorbeeld te kijken, kunnen we onze loop die van 0 tot 9 loopt repliceren met een oneindige loop als volgt:

i=0while true
do
    if [ $i -eq 10 ]
    then
        break
    fi
    echo $i
    let i=i+1
done

Als je meerdere geneste while-lussen hebt, kun je een nummer toevoegen na de break-verklaring om aan te geven uit welk niveau van de lus je wilt breken: break 1 is hetzelfde als break en zal uit de dichtstbijzijnde omringende lus stappen, break 2 zal uit de lus hierboven stappen, etc.

Laten we snel een voorbeeld bekijken, dit keer met for-lussen, waarbij elk vierletterwoord wordt doorlopen tot het woord “bash” wordt bereikt:

for l4 in {a..z}
do
    for l3 in {a..z}
    do
        for l2 in {a..z}
        do
            for l1 in {a..z}
            do
                echo "$l4$l3$l2$l1"
                if [ $l4 = "b" -a $l3 = "a" -a $l2 = "s" -a $l1 = "h" ]
                then
                    break 4
                fi
            done
        done
    done
done

A related keyword that’s also worth a mention is continue, which skips to the next iteration of the loop. Just like break, it also takes an optional numeric argument that corresponds to the loop level.

Hier is een grappig voorbeeld waarin we alle woorden met de letter E overslaan in onze verkorte lijst met vierletterwoorden:

for l4 in {a..z}
do
    if [ $l4 = "e" ]
    then
        continue
    fi
    for l3 in {a..z}
    do
        if [ $l3 = "e" ]
        then
            continue
        fi
        for l2 in {a..z}
        do
            if [ $l2 = "e" ]
            then
                continue
            fi
            for l1 in {a..z}
            do
                if [ $l1 = "e" ]
                then
                    continue
                fi
                echo "$l4$l3$l2$l1"
                if [ $l4 = "b" -a $l3 = "a" -a $l2 = "s" -a $l1 = "h" ]
                then
                    break 4
                fi
            done
        done
    done
done

We kunnen ook al deze continue-verklaringen op het diepste lusniveau uitvoeren:

for l4 in {a..z}
do
    for l3 in {a..z}
    do
        for l2 in {a..z}
        do
            for l1 in {a..z}
            do
                if [ $l4 = "e" ]
                then
                    continue 4
                fi
                if [ $l3 = "e" ]
                then
                    continue 3
                fi
                if [ $l2 = "e" ]
                then
                    continue 2
                fi
                if [ $l1 = "e" ]
                then
                    continue
                fi
                echo "$l4$l3$l2$l1"
                if [ $l4 = "b" -a $l3 = "a" -a $l2 = "s" -a $l1 = "h" ]
                then
                    break 4
                fi
            done
        done
    done
done
Our script stops once it generates the word “bash”

Hoe je gebruikersinvoer krijgt in een shell-script

Soms wil je dat de gebruiker direct met je script communiceert in plaats van alleen maar initiële scriptargumenten te gebruiken. Daar komt het read-commando van pas.

Om gebruikersinvoer te verkrijgen en op te slaan in een variabele genaamd NAAM, gebruik je dit commando:

read NAME 

Dit is de eenvoudigste vorm van het commando, bestaande uit alleen de commandonaam en de variabele waarin je de invoer wilt opslaan.

Vaker wil je echter de gebruiker een prompt geven zodat ze weten wat ze moeten typen. Dat doe je met het argument -p, waarna je jouw voorkeursprompt schrijft.

Hier is hoe je om een naam kunt vragen, en deze toewijst aan een variabele genaamd NAAM:

read -p "Your name: " NAME
echo "Your name is $NAME." # this line is here just to show that the name has been saved to the NAME variable
The script saves our input to a variable and then prints it

Het afdrukken van speciale tekens in een string

Er zijn een aantal tekens in Bash waar je voorzichtig mee moet zijn. Bijvoorbeeld, spaties in bestandsnamen, aanhalingstekens in strings, of backslashes zo ongeveer overal.

Om Bash te vertellen hun speciale betekenis op bepaalde plaatsen te negeren, kun je ze ofwel “escapen” of ze omringen met een letterlijk aanhalingsteken.

Escapen” van een speciaal teken betekent Bash vertellen om het te behandelen als gewoon een teken zonder speciale betekenis. Om dat te doen, schrijf je een backslash vóór dat teken.

Laten we zeggen dat we een bestand hebben met de naam img \ 01 *DRAFT*, bijvoorbeeld. In Bash kunnen we er als volgt naar verwijzen:

img\ \\\ 01\ \*DRAFT\*

Hier is een niet-uitputtende lijst van speciale tekens in Bash:

  • Witruimte: spatie, tab, lege regel
  • Aanhalingstekens: ”, “”
  • Haakjes en vierkante brackets: ( ), { }, [ ]
  • Pijpen en omleidingen: |, <, >
  • Wildcard tekens: *, ?
  • Diversen: !, #, ;, =, &, ~, `
  • Het escape-teken zelf: \

Als je nieuw bent in Bash, kan het echter lastig zijn om te onthouden welke tekens speciale betekenis hebben. Daarom kan het in veel situaties makkelijker zijn om een letterlijk aanhalingsteken te gebruiken: Omring de tekst met speciale tekens gewoon met enkele aanhalingstekens, en alle speciale tekens binnen die aanhalingstekens zullen genegeerd worden.

Hier is hoe dat eruit zou zien voor ons voorbeeld:

'img \ 01 *DRAFT*'

Wat als je wel een speciaal karakter wilt gebruiken, maar de anderen wilt escapen? Je zou elk ander karakter kunnen escapen met een backslash, maar je kunt jezelf ook de moeite besparen en alles behalve dat speciale karakter omringen met letterlijke aanhalingstekens.

Bijvoorbeeld, stel dat je verschillende bestanden hebt genaamd img \ 01 *v1 DRAFT*, img \ 01 *v2 DRAFT*, img \ 01 *ROUGH DRAFT*, enz., en je wilt een glob-uitbreiding gebruiken om al die bestandsnamen te matchen. Hier is wat je zou kunnen schrijven:

'img \ 01 *'*' DRAFT*'
This glob expansion finds all of our 3 oddly-named files

Als wat je moet schrijven een enkele aanhalingsteken bevat – bijv. img \ 01 *’FINAL’* – kun je een vergelijkbare strategie gebruiken, door letterlijke strings en escapen te combineren:

'img \ 01 '\''FINAL'\'

Hoe je strings kunt samenvoegen in Bash

Stel dat je twee of meer stringvariabelen hebt – bijvoorbeeld een voornaam en achternaam:

FIRST_NAME="Johnny"LAST_NAME="Appleseed"

Om deze variabelen samen te voegen tot één string, wellicht met een aangepaste scheidingsteken, maak simpelweg een nieuwe string bestaande uit die twee variabelen:

NAME="$LAST_NAME"', '"$FIRST_NAME"

Je kunt ook dubbele aanhalingstekens gebruiken met inline variabelen hiervoor, door middel van accolades om variabelenamen te scheiden van de omliggende tekst:

NAME="${LAST_NAME}, ${FIRST_NAME}"

Bash staat ook het gebruik van de +=-operator toe om tekst aan een string toe te voegen, zoals dit:

NAME='Appleseed'NAME+=', 'NAME+='Johnny'
Examples of different ways of stringing together text

Commando’s uitvoeren in een string

Bash biedt ook de mogelijkheid om de uitvoer van een opdracht binnen een tekenreeks te gebruiken, ook wel bekend als command substitution. Plaats eenvoudigweg uw opdracht tussen $(). Bijvoorbeeld, om een actuele tijdstempel af te drukken, kunt u dit uitvoeren:

echo "Current timestamp: $(date)"
Using command substitution to print the current timestamp

Je herinnert je deze syntaxis mogelijk ook van een eerdere for-lus voorbeeld, toen we door een reeks van gehele getallen van 0 tot 9 gingen:

for i in $(seq 0 1 9)
do
    echo $i
done

De gesubstitueerde opdracht wordt uitgevoerd in een subshell. Dit betekent dat, bijvoorbeeld, eventuele variabelen die tijdens de opdracht zijn aangemaakt, geen invloed zullen hebben op de omgeving waarin u uw script uitvoert.

Het instellen en retourneren van exitcodes in een shellscript

Voor een meer complex script is het gebruikelijk om het een exit code te laten retourneren — een getal tussen 0 en 255 dat aangeeft of het script succesvol is uitgevoerd of een fout heeft ondervonden.

Wat betreft welke getallen te gebruiken, specificeert de officiële Bash-handleiding deze:

  • 0: Programma succesvol uitgevoerd.
  • 2: Programma verkeerd gebruikt (bijv. als gevolg van ongeldige of ontbrekende argumenten).
  • 1 en 3-124: Door gebruiker gedefinieerde fouten.
  • 126: Opdracht is niet uitvoerbaar.
  • 127: Opdracht niet gevonden.
  • 125 en 128-255: Foutstatussen die de shell gebruikt. Als een proces wordt gestopt door een signaal N, is de afsluitstatus 128 + N.

Zoals je kunt zien, geven alle getallen behalve 0 een soort fout aan. De exitcode 1 wordt vaak gebruikt voor algemene fouten. In de meeste gevallen zul je geen exitcode boven 2 nodig hebben.

Om een exitcode vanuit je script te retourneren, gebruik je gewoon het exit-commando. Bijvoorbeeld, om af te sluiten met een code van 2, zou je schrijven exit 2.

Als je het exit-commando niet gebruikt in je script of het commando gebruikt zonder een code te specificeren, zal de exitstatus van het laatst uitgevoerde commando in je script worden geretourneerd.

Om de exitcode van het laatst uitgevoerde commando in je shell te verkrijgen, gebruik je de $?-variabele: echo $?.

Hoe roep je een functie aan

Bij het schrijven van een langer script of een met herhalende codeblokken, wil je misschien wat code afsplitsen in functies. Er zijn twee formaten die je kunt gebruiken om functies te definiëren: In beide gevallen wordt alle functiecode binnen accolades geplaatst en verschilt alleen de functieverklaring.

Het compactere formaat gebruikt haakjes die de functienaam volgen om een functie te declareren:

function_name () {
    echo "This is where your function code goes"
}

Het andere formaat gebruikt het function-sleutelwoord voor een functienaam:

function function_name {
    echo "This is where your function code goes"
}

Functies moeten worden gedeclareerd voordat ze worden aangeroepen in uw script. U roept een functie aan net zoals u een reguliere opdracht uitvoert, door de functienaam te gebruiken als de opdracht:

function_name

Door gegevens door te geven aan een functie met behulp van variabelen

In Bash kunnen functies geen argumenten aannemen. Om informatie naar een functie te sturen, moet u globale variabelen gebruiken in uw script.

Bijvoorbeeld:

is_your_name_defined () {
    if [ -z "$YOUR_NAME" ]
    then
        echo "It doesn't seem like I have your name."
    else
        echo "Is this your name: ${YOUR_NAME}?"
    fi
}
read -p "Your name: " YOUR_NAME

is_your_name_defined

In tegenstelling tot wat u gewend bent in andere talen, zijn de variabelen die u binnen uw functie definieert globaal en zichtbaar voor de code buiten uw script. Om een variabele lokaal te definiëren die alleen toegankelijk is voor uw functie (dus niet toegankelijk voor alle code buiten), gebruikt u het lokale trefwoord: bijv. lokale i=0.

Als u waarden wilt retourneren vanuit een functie, moet u ook globale variabelen gebruiken. In Bash kunnen functies alleen exitcodes retourneren door gebruik te maken van het return trefwoord. Laten we eens naar een voorbeeld kijken:

is_your_name_defined () {
    if [ -z "$YOUR_NAME" ]
    then
        MESSAGE="It doesn't seem like I have your name."
    else
        MESSAGE="Is this your name: ${YOUR_NAME}?"
    fi
}
read -p "Your name: " YOUR_NAME

is_your_name_defined

echo $MESSAGE
The output of our script depends on the values entered

Samenvatting

Bash-scripting stelt u in staat om vrij veel te doen op een op UNIX gebaseerd besturingssysteem. Dit artikel behandelde enkele basisprincipes van Bash-scripting, waaronder het maken en uitvoeren van scripts, werken met strings en het gebruiken van lussen in uw code. Hopelijk dient het als een goede start van uw reis in het schrijven van krachtige Bash-scripts die aan uw behoeften voldoen.

Er valt echter nog veel meer te leren over Bash, waaronder enkele van de meest nuttige commando’s, bestandsnavigatie en meer. Laat ons in de opmerkingen weten welke onderwerpen we hierna moeten behandelen.

Gerelateerd Artikel:

Source:
https://petri.com/shell-scripting-bash/