
Voorwaardelijke tests vertakken de uitvoeringsstroom van Linux Bash-scripts volgens het resultaat van een logische expressie. Voorwaardelijke tests met dubbele haakjes vereenvoudigen de syntaxis aanzienlijk, maar hebben nog steeds hun eigen problemen.
Enkele en dubbele beugels
Bash biedt de test opdracht. Hiermee kunt u logische uitdrukkingen testen. De expressie retourneert een antwoord dat een waar of onwaar antwoord aangeeft. Een echte respons wordt aangegeven door een retourwaarde van nul. Alles anders dan nul duidt op onwaar.
Opdrachten op de opdrachtregel koppelen met de && operator gebruikt deze functie. Opdrachten worden alleen uitgevoerd als de vorige opdracht met succes is voltooid.
Als de test waar is, wordt het woord “Ja” afgedrukt.
test 15 -eq 15 && echo "Yes"
test 14 -eq 15 && echo "Yes"

De voorwaardelijke tests met één haakje bootsen de test opdracht. Ze zetten de uitdrukking tussen haakjes “[ ]” en werken net als de test opdracht. In feite zijn ze hetzelfde programma, gemaakt op basis van dezelfde broncode. Het enige operationele verschil is hoe de test versie en de [ version handle help requests.
This is from the source code:
/* Recognize --help or --version, but only when invoked in the "[" form, when the last argument is not "]". Gebruik directe parsing, in plaats van parse_long_options, om te voorkomen dat afkortingen worden geaccepteerd. POSIX staat "[ --help" and "[ --version" to have the usual GNU behavior, but it requires "test --help" and "test --version" to exit silently with status 0. */
We can see the effect of this by asking test and [ for help and checking the response code sent to Bash.
test --help
echo $?
[ --help
echo $?

Both test and [ are shell builtins, meaning they are baked right into Bash. But there’s also a standalone binary version of [ .
type test
type [
whereis [

By contrast, the double bracket conditional tests [[ and ]] zijn trefwoorden. [[ and ]] voeren ook logische tests uit, maar hun syntaxis is anders. Omdat het trefwoorden zijn, kunt u enkele handige functies gebruiken die niet werken in de versie met één haakje.
De trefwoorden met dubbele haakjes worden ondersteund door Bash, maar zijn niet beschikbaar in elke andere shell. De Korn-schaal ondersteunt ze bijvoorbeeld wel, maar de gewone oude schaal, sh, niet. Al onze scripts beginnen met de regel:
#!/bin/bash
Dit zorgt ervoor dat we de Bash-shell aanroepen om het script uit te voeren.
Ingebouwde en trefwoorden
We kunnen de compgen programma om de ingebouwde functies weer te geven:
compgen -b | fmt -w 70
Zonder de uitvoer erdoor te leiden fmt we zouden een lange lijst krijgen met elke ingebouwde op zijn eigen regel. In dit geval is het handiger om de ingebouwde elementen gegroepeerd in een alinea te zien.

We kunnen zien test en [ in the list, but ] staat niet vermeld. De [ command looks for a closing ] om te detecteren wanneer het het einde van de uitdrukking heeft bereikt, maar ] is geen aparte ingebouwde. Het is slechts een signaal dat we geven aan [ to indicate the end of the parameter list.
To see the keywords, we can use:
compgen -k | fmt -w 70

The [[ and ]] trefwoorden staan beide in de lijst, omdat [[ is a one keyword and ]] is een ander. Ze zijn een matched pair, net als if en fi , en case en esac .
Wanneer Bash een script (of een opdrachtregel) aan het ontleden is en een trefwoord detecteert dat een overeenkomend, sluitend trefwoord heeft, verzamelt het alles wat ertussen verschijnt en past het elke speciale behandeling toe die de trefwoorden ondersteunen.
Met een ingebouwde opdracht wordt wat volgt op de ingebouwde opdracht precies zoals parameters aan elk ander opdrachtregelprogramma doorgegeven. Dit betekent dat de auteur van het script speciale aandacht moet besteden aan zaken als spaties in variabele waarden.
Shell Globbing
Bij voorwaardelijke tests met dubbele haakjes kan gebruik worden gemaakt van shell globbing. Dit betekent het sterretje “*‘ zal uitbreiden naar ‘alles’.
Typ of kopieer de volgende tekst in een editor en sla deze op in een bestand met de naam “whelkie.sh”.
#!/bin/bash stringvar="Whelkie Brookes" if [[ "$stringvar" == *elk* ]]; then echo "Warning contains seafood" else echo "Free from molluscs" fi
Om het script uitvoerbaar te maken, moeten we de . gebruiken chmod commando met de -x (uitvoeren) optie. U moet dit bij alle scripts in dit artikel doen als u ze wilt uitproberen.
chmod +x whelkie.sh

Wanneer we het script uitvoeren, zien we dat de tekenreeks “elk” is gevonden in de tekenreeks “Whelkie”, ongeacht welke andere tekens eromheen staan.
./whelkie.sh

Een punt om op te merken is dat we de zoekreeks niet tussen dubbele aanhalingstekens plaatsen. Als je dat doet, zal de globbing niet gebeuren. De zoekstring wordt letterlijk behandeld.
Andere vormen van shell globbing zijn toegestaan. Het vraagteken “?” komt overeen met enkele tekens, en enkele vierkante haken worden gebruikt om reeksen tekens aan te geven. Als u bijvoorbeeld niet weet welk geval u moet gebruiken, kunt u beide gevallen afdekken met een bereik.
#!/bin/bash stringvar="Jean-Claude van Clam" if [[ "$stringvar" == *[cC]lam* ]]; then echo "Warning contains seafood." else echo "Free from molluscs." fi
Sla dit script op als “damme.sh” en maak het uitvoerbaar. Wanneer we het uitvoeren, wordt de voorwaardelijke instructie omgezet in true en wordt de eerste clausule van de if-instructie uitgevoerd.
./damme.sh

Strings citeren
We noemden het al eerder omwikkelen van strings tussen dubbele aanhalingstekens. Als je dat doet, zal shell globbing niet optreden. Hoewel de conventie zegt dat het een goede gewoonte is, doe je dat niet nodig hebben om tekenreeksvariabelen tussen aanhalingstekens te plaatsen bij gebruik [[ and ]]zelfs als ze spaties bevatten. Kijk naar het volgende voorbeeld. Beide $stringvar en $surname stringvariabelen bevatten spaties, maar geen van beide staat tussen aanhalingstekens in de voorwaardelijke instructie.
#!/bin/bash stringvar="van Damme" surname="van Damme" if [[ $stringvar == $surname ]]; then echo "Surnames match." else echo "Surnames don't match." fi
Sla dit op in een bestand met de naam “achternaam.sh” en maak het uitvoerbaar. Voer het uit met:
./surname.sh

Ondanks dat beide strings spaties bevatten, slaagt het script en wordt de voorwaardelijke instructie omgezet in true. Dit is handig bij het omgaan met paden en mapnamen die spaties bevatten. Hier de -d optie retourneert true als de variabele een geldige mapnaam bevat.
#!/bin/bash
dir="/home/dave/Documents/Needs Work"
if [[ -d ${dir} ]];
then
echo "Directory confirmed"
else
echo "Directory not found"
fi
Als u het pad in het script wijzigt om een map op uw eigen computer weer te geven, de tekst opslaat in een bestand met de naam “dir.sh” en het uitvoerbaar maakt, kunt u zien dat dit werkt.
./dir.sh

Bestandsnaam Globbing Gotchas
Een interessant verschil tussen [ ] en [[ ]] heeft betrekking op bestandsnamen met globbing erin. De vorm “*.sh” komt overeen met alle scriptbestanden. Enkele haakjes gebruiken [ ] mislukt tenzij er een enkel scriptbestand is. Het vinden van meer dan één script geeft een fout.
Hier is het script met voorwaarden voor enkele haakjes.
#!/bin/bash if [ -a *.sh ]; then echo "Found a script file" else echo "Didn't find a script file" fi
We hebben deze tekst opgeslagen in “script.sh” en uitvoerbaar gemaakt. We controleerden hoeveel scripts er in de directory stonden en voerden het script uit.
ls
./script.sh

Bash geeft een fout. We hebben op één na alle scriptbestanden verwijderd en het script opnieuw uitgevoerd.
ls
./script.sh

De voorwaardelijke test retourneert waar en het script veroorzaakt geen fout. Het script bewerken om dubbele haakjes te gebruiken, levert een derde type gedrag op.
#!/bin/bash if [[ -a *.sh ]]; then echo "Found a script file" else echo "Didn't find a script file" fi
We hebben dit opgeslagen in een bestand met de naam “dscript.sh” en het uitvoerbaar gemaakt. Als u dit script uitvoert in een map met veel scripts erin, wordt er geen fout gegenereerd, maar het script herkent geen scriptbestanden.
De voorwaardelijke instructie die dubbele haakjes gebruikt, wordt alleen omgezet in true in het onwaarschijnlijke geval dat u een bestand met de naam “*.sh” in de directory heeft.
./dscript.sh

Logische AND en OR
Dubbele beugels laten u gebruiken && en || als de logische AND- en OR-operatoren.
Dit script zou de voorwaardelijke instructie moeten omzetten in true omdat 10 gelijk is aan 10 en 25 is minder dan 26.
#!/bin/bash first=10 second=25 if [[ first -eq 10 && second -lt 26 ]]; then echo "Condition met" else echo "Condition failed" fi
Sla deze tekst op in een bestand met de naam “and.sh”, maak het uitvoerbaar en voer het uit met:
./and.sh

Het script wordt uitgevoerd zoals we zouden verwachten.
Deze keer gebruiken we de || exploitant. De voorwaardelijke instructie moet worden opgelost in waar, want hoewel 10 niet groter is dan 15, is 25 nog steeds kleiner dan 26. Zolang de eerste vergelijking of de tweede vergelijking is waar, de voorwaardelijke verklaring als geheel wordt waar.
Sla deze tekst op als “or.sh” en maak hem uitvoerbaar.
#!/bin/bash first=10 second=25 if [[ first -gt 15 || second -lt 26 ]]; then echo "Condition met." else echo "Condition failed." fi
./or.sh

Regexes
Voorwaardelijke uitspraken met dubbele haakjes staan het gebruik van de . toe =~ operator, die de regex-zoekpatronen in een tekenreeks toepast op de andere helft van de instructie. Als aan de regex wordt voldaan, wordt de voorwaardelijke verklaring als waar beschouwd. Als de regex geen overeenkomsten vindt, wordt de voorwaardelijke instructie omgezet in false.
Sla deze tekst op in een bestand met de naam “regex.sh” en maak het uitvoerbaar.
#!/bin/bash
words="one two three"
WordsandNumbers="one 1 two 2 three 3"
email="dave@fabricateddomain.co.uk"
mask1="[0-9]"
mask2="[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}"
if [[ $words =~ $mask1 ]];
then
echo ""$words" contains digits."
else
echo "No digits found in "$words"."
fi
if [[ $WordsandNumbers =~ $mask1 ]];
then
echo ""$WordsandNumbers" contains digits."
else
echo "No digits found in "$WordsandNumbers"."
fi
if [[ $email =~ $mask2 ]];
then
echo ""$email" is a valid e-mail address."
else
echo "Couldn't parse "$email"."
fi
De eerste set dubbele haakjes gebruikt de tekenreeksvariabele $mask1 als de regex. Dit bevat het patroon voor alle cijfers in het bereik van nul tot negen. Het past deze regex toe op de $words string variabele.
De tweede set dubbele haakjes gebruikt opnieuw de stringvariabele $mask1 als de regex, maar deze keer gebruikt het het met de $WordsandNumbers string variabele.
De laatste set dubbele haakjes gebruikt een complexer regex-masker in stringvariabele $mask2 .
-
[A-Za-z0-9._%+-]+: Dit komt overeen met elk teken dat een hoofdletter of kleine letter is, of een cijfer van nul tot negen, of een punt, onderstrepingsteken, percentageteken of plus- of minteken. De “
+” buiten de “[]” betekent herhaal die overeenkomsten voor zoveel tekens als het vindt. - @: Dit komt alleen overeen met het teken “@”.
-
[A-Za-z0-9.-]+: Dit komt overeen met elk teken dat een hoofdletter of kleine letter is, of een cijfer van nul tot negen, of een punt of een koppelteken. De “
+” buiten de “[ ]” betekent herhaal die overeenkomsten voor zoveel tekens als het vindt. - .: Dit komt overeen met de “.” alleen karakter.
-
[A-Za-z]{2,4}: Dit komt overeen met elke hoofdletter of kleine letter. De “
{2,4}” betekent overeenkomen met ten minste twee tekens en maximaal vier.
Als je dat allemaal samenvoegt, controleert het regex-masker of een e-mailadres correct is gevormd.
Sla de scripttekst op in een bestand met de naam “regex.sh” en maak het uitvoerbaar. Wanneer we het script uitvoeren, krijgen we deze uitvoer.
./regex.sh

De eerste voorwaardelijke instructie mislukt omdat de regex naar cijfers zoekt, maar er zijn geen cijfers in de waarde in de $words string variabele.
De tweede voorwaardelijke verklaring slaagt omdat de $WordsandNumbers stringvariabele bevat wel cijfers.
De laatste voorwaardelijke instructie slaagt – dat wil zeggen, het wordt omgezet in waar – omdat het e-mailadres correct is opgemaakt.
Slechts één voorwaarde
Voorwaardelijke tests met dubbele haakjes zorgen voor flexibiliteit en leesbaarheid van uw scripts. Alleen al het kunnen gebruiken van regexes in uw voorwaardelijke tests rechtvaardigt het leren gebruiken [[ and ]].
Zorg ervoor dat het script een shell aanroept die ze ondersteunt, zoals Bash.