Voorwaardelijke tests met dubbele beugel gebruiken in Linux

fatmawati achmad zaenuri/Shutterstock.com

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"

Eenvoudige voorbeelden van het Bash-testcommando

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 $?

Using --help on test and [

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 [

Finding the different types of [ and test commands

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.

De ingebouwde Bash weergeven

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

Listing the Bash keywords

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

chmod gebruiken om een ​​script uitvoerbaar te maken

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

Het script wulkie.sh uitvoeren

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

Het damme.sh-script uitvoeren

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

Het script achternaam.sh uitvoeren

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

Het dir.sh-script uitvoeren

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

Het script.sh-script uitvoeren

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

ls
./script.sh

Het script.sh-script uitvoeren met een enkel script in de directory

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

Het dscript.sh-script uitvoeren

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 and.sh-script uitvoeren

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

Het or.sh-script uitvoeren

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

Het regex.sh-script uitvoeren

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.

Nieuwste artikelen

Gerelateerde artikelen