Later toegevoegd: Hoewel alles wat hieronder beschreven is wel werkt wordt in de meeste Bash scripts niet (( ... )) voor vergelijkingen met getallen gebruikt maar [ ... ] of soms ook [[ ... ]]. Best wel opmerkelijk omdat (( ... )) al sinds 1996 in Bash zit, maar het is dus niet gebruikelijk. Deze lesstof is dus niet zo goed als ik dacht toen ik het herschreef. Voor gevorderden is het wel interessant denk ik.Hoi allemaal,
Bij ClubNix (Linux-gebruikers in Den Haag) zijn we bezig lesmateriaal te maken voor onze cursus Bash scripts schrijven. Misschien zijn er hier mensen die het leuk vinden om mee te denken? Van een bestaande HOW-TO voor beginners over Bash scripts schrijven heb ik nu één hoofdstuk helemaal herschreven. Het is een HOW-TO die op de website The Linux Documentation Project staat en die onder de GNU Free Documentation License valt. Het is dus open content en kan dus bewerkt en verder verspreid worden volgens de regels van de GNU Free Documentation License.
Hieronder de herschreven versie van hoofdstuk
6. Voorwaardelijke opdrachten. Het Nederlandse origineel staat hier:
http://doets.xs4all.nl/HOWTO/HTML/nl/Bash-Prog-Intro-NL/Bash-Prog-Intro-HOWTO-NL.html . En het Engelse origineel staat hier op The Linux Documentation Project:
http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.htmlWat heb ik gebruikt als bronnen voor mijn wijzigingen? In de
"Advanced Bash-Scripting Guide" op The Linux Documentation Project zijn heel veel details van Bash scripting uitgeplozen. En ik heb ook delen van de man page van Bash goed doorgelezen, helemaal onderaan staat welke delen precies.
Dit is trouwens gekopieerd uit een OpenOffice.org document en in dat document is de opmaak beter. Het staat hier:
http://www.clubnix.net/forum/index.php?topic=556.0Deze lesstof is bedoeld voor mensen met een redelijke voorkennis van Linux en met weinig of geen voorkennis van Bash shell scripts. Het is niet bedoeld voor mensen die een uitstekende kennis hebben van Linux en ook al redelijk Bash shell scripts kunnen schrijven. Daarom probeer ik per se te vermijden te vertellen dat je bij
if...then...else...fi zoiets gebruikt als een
exit status. Er zijn al genoeg moeilijke dingen en eigenaardigheden zonder dat te vertellen.
Bedankt aan iedereen die wil reageren. En heel erg bedankt als je verbeteringen hebt!
Oh en nog iets anders. Onze eerste les van de cursus Bash scripts schrijven bij ClubNix was een mislukking
Het was te moeilijk en we hadden gewoon geen goede lesstof. Dus vandaar dat we nu maar een al bestaande HOW-TO nog een stuk gaan verbeteren. En als je me nog goede boeken over Bash scripts schrijven kan aanraden: PB me
Veel plezier met Ubuntu,
Paulus/laudaka
Lesmateriaal Bash scripts schrijven, niveau C6. Voorwaardelijke opdrachtenDit hoofdstuk is herschreven door Paulus.
Voorwaardelijke opdrachten laten Bash een beslissing nemen of een actie wel of niet uitgevoerd zal worden. De beslissing wordt genomen door een
voorwaarde te evalueren en te kijken of die
voorwaarde wel waar of niet waar oplevert.
6.1 Droge TheorieVoorwaardelijke opdrachten bestaan er in vele vormen. De basisvorm is:
if voorwaarde then opdracht fi. Hierbij wordt opdracht alleen uitgevoerd wanneer de
voorwaarde wel waar is. En het zal je niet verbazen dat de opdracht niet wordt uitgevoerd als de
voorwaarde niet waar is.
“2 < 1” is een
voorwaarde die niet waar oplevert, terwijl “2 > 1” een
voorwaarde is die wel waar oplevert.
Er zijn uitgebreidere vormen van voorwaardelijke opdrachten, zoals:
if voorwaarde then opdracht1 else opdracht2 fi. Hier wordt
opdracht1 uitgevoerd als de
voorwaarde wel waar oplevert, anders wordt
opdracht2 uitgevoerd.
In een Bash script schrijf je het zo. Het inspringen, en het regeleinde na
then zijn niet verplicht maar ik raad beginners van harte aan
if-constructies op deze manier te schrijven:
if voorwaarde
then
opdracht1
else
opdracht2
fi
6.2 Voorbeeld: Voorwaardelijke opdracht if, then, fi met getallen#!/bin/bash
if (( 2 > 1 ))
then
echo "voorwaarde leverde op: wel waar."
fiZoals je ziet gebruik je bij getallen dubbele gewone haakjes (( ... )) om een
voorwaarde te schrijven.
6.3 Voorbeeld: Voorwaardelijke opdracht if, then, fi met strings#!/bin/bash
if [[ "Tux pinguin" == "Tux pinguin" ]]
then
echo "Voorwaarde leverde op: wel waar."
fi
Zoals je ziet gebruik je bij strings dubbele vierkante haakjes [[ ... ]] om een
voorwaarde te schrijven.
6.4 Voorbeeld: Voorwaardelijke opdracht if, then, else, fi#!/bin/bash
if [[ "Tux pinguin" == "BSD duiveltje" ]]
then
echo "Voorwaarde leverde op: wel waar."
else
echo "Voorwaarde leverde op: niet waar."
echo "Dat is geen verassing, dat de strings Tux pinguin"
echo "en BSD duiveltje niet hetzelfde zijn!"
fi
Na de
then en na de
else mogen meerdere opdrachten staan.
6.5 Voorbeeld: Voorwaardelijke opdrachten met variabelen#!/bin/bash
stad1="Apeldoorn"
stad2="Zaandam"
if [[ "$stad1" > "$stad2" ]]
then
echo "Voorwaarde leverde op: wel waar."
else
echo "Voorwaarde leverde op: niet waar."
fi
Dit ziet er op het eerste gezicht raar uit. Mag je bij strings ook kleiner dan (<) en groter dan (>) gebruiken? Ja, dat kan dus omdat Bash door de [[ ... ]] weet dat het om strings gaat. De strings worden dan vergeleken zoals je woorden in alfabetische volgorde sorteert, en niet zoals getallen vergeleken worden.
6.6 Overzicht van veelvoorkomende vergelijkingen in voorwaardenVoorwaarden met getallen | Levert waar op als |
(( "$getal1" == "$getal2" )) | getal1 is gelijk aan getal2 |
(( "$getal1" != "$getal2" )) | getal1 is niet gelijk aan getal2 |
(( "$getal1" < "$getal2" )) | getal1 is kleiner dan getal2 |
(( "$getal1" <= "$getal2" )) | getal1 is kleiner dan óf gelijk aan getal2 |
(( "$getal1" > "$getal2" )) | getal1 is groter dan getal2 |
(( "$getal1" >= "$getal2" )) | getal1 is groter dan óf gelijk aan getal2 |
Voorwaarden met strings | Levert waar op als |
[[ "$string1" == "$string2" ]] | string1 is gelijk aan string2 |
[[ "$string1" != "$string2" ]] | string1 is niet gelijk aan string2 |
[[ "$string1" < "$string2" ]] | string1 komt alfabetisch eerder dan string2 |
[[ "$string1" > "$string2" ]] | string1 komt alfabetisch later dan string2 |
[[ -z "$string1" ]] | string1 is zero-length: hetzij string1 is leeg, hetzij string1 bestaat helemaal niet |
[[ -n "$string1" ]] | string1 is niet-zero-length: string1 bestaat en is niet leeg |
6.7 Eigenaardigheden en adviezen* Op sommige plaatsen op internet zul je in plaats van
[[ string1 == string ]] het oudere
[[ string1 = string ]] tegenkomen met één is-gelijk-teken. Ik raad om meerdere redenen af die variant te gebruiken. De beste reden om altijd een dubbel is-gelijk-teken te gebruiken is omdat het zo niet lijkt op de toekenning aan een variabele, dat gaat immers met
var=inhoud.
* Het kan zijn dat je op internet in voorbeelden het oudere
[ ... ] of
test tegenkomt voor zowel getallen als strings. Ik raad je aan de twee nieuwere manieren te gebruiken met
(( ... )) voor getallen en
[[ ... ]] voor strings. Daar maak je minder snel fouten mee.
* De aanhalingstekens om variabelen heen zijn zelfs voor doorgewinterde programmeurs een eigenaardigheid van de Bash shell. Het zou meestal zonder aanhalingstekens kunnen. De reden dat het toch een goed idee is om de aanhalingstekens te gebruiken is dat Bash foutmeldingen kan geven als een variabele die in een
voorwaarde staat leeg is.
* Voor de mensen van Niveau D die dit lezen: Als je gewend bent het oudere
[ ... ] te gebruiken met
-eq,
-ne,
-lt,
-le,
-gt,
-ge dan raad ik je aan in ieder geval over te stappen naar
[[ ... ]] als je toch niet
(( ... )) wil gebruiken voor getallen.
[[ ... ]] doet vrijwel altijd precies wat je bedoelt, de oudere vorm geeft soms onverwachte resultaten.
6.8 Meer lezen over voorwaardelijke opdrachtenHoewel onderstaand hoofdstuk uit de "Advanced Bash-Scripting Guide" wel op Niveau D is en niet op Niveau C, staan er wel veel voorbeelden in die dingen een stuk duidelijker maken.
* Internetdocument: Cooper, Mendel. Advanced Bash-Scripting Guide. Website van The Linux Documentation Project, 2011.
Chapter 7. Tests.
http://tldp.org/LDP/abs/html/tests.htmlDeze posting in dit topic is beschikbaar onder de
GNU Free Documentation License. Kopiëren, wijzigen en/of verspreiden toegestaan op voorwaarde dat je je aan die licentie houdt. Auteur van deze posting: Paulus Santané (laudaka). Deze posting is een sterk gewijzigde versie van hoofdstuk 6 uit
"BASH Programming - Introduction HOW-TO" op The Linux Documentation Project geschreven door Mike G. Vertaald onder de naam
"BASH Programmering - Introductie HOW-TO" door Ellen Bokhorst.
N.B. Dit stuk hieronder is alleen bedoeld voor mensen die mee willen helpen de bovenstaande informatie te controleren. Want de man page van Bash is echt één van de man pages die een afrader is voor beginners en matig gevorderden.
Referenties Hoofdstuk 6. Voorwaardelijke opdrachten:
* man bash, kop SHELL GRAMMAR, subkop Compound Commands, paragraaf if list; then list; [ elif list; then list; ] ... [ else list; ] fi
* man bash, kop SHELL GRAMMAR, subkop Compound Commands, paragraaf ((expression))
* De constructie ((expression)) wordt geëvalueerd zoals omschreven in man bash, kop ARITHMETIC EVALUATION
* man bash, kop SHELL GRAMMAR, subkop Compound Commands, paragraaf [[ expression ]]
* De constructie [[ expression ]] wordt geëvalueerd zoals omschreven in man bash, kop CONDITIONAL EXPRESSIONS.