Tips en Trucs 2018

Krachtige variabelen

Bash variabelen worden meestal enkel gebruikt als plaatshouders voor het opslaan van waarden en gegevens. Je kunt ze echter uitbreiden met modifiers (expansion modifiers) om er zo meer uit te halen.

Een waarde aan een variabele toekennen en opvragen

De naam van een variabele mag enkel bestaan uit alfanumerieke tekens en underscore tekens en mag niet beginnen met een cijfer. Tevens mogen er geen spaties voor of achter het gelijkteken staan.

dany@pindabook:~> variabele_1="een waarde"

Een waarde opslaan in een variabele heeft enkel zin als je de waarde later nog wilt gebruiken. Om de waarde terug op te vragen, plaats je voor de naam van de variabele een dollarteken. De naam van de variabele mag je daarbij tussen accolades plaatsen.

dany@pindabook:~> echo $variabele_1 ${variabele_1} 
een waarde een waarde

Belangrijk is dat voor de opdracht enkel de waarde van de variabele zichtbaar is. M.a.w. eerst wordt de waarde van de variabele opgehaald en dan pas wordt de opdracht met de opgehaalde waarde uitgevoerd. Indien de waarde dus spaties bevat zal de opdracht de waarde opsplitsen in verschillende parameters. Om de waarde als één geheel aan de opdracht door te geven, moet je ze tussen aanhalingstekens plaatsen.

dany@pindabook:~> printf "%s\n" ${variabele_1}
een
waarde
dany@pindabook:~> printf "%s\n" "${variabele_1}"
een waarde

Expansion modifiers

Binnen de accolades kan je na de naam van de variabele bewerkingen (operatoren) plaatsen. Deze bewerkingen passen de waarde binnen de variabele niet aan, maar wel de weergave waarbij ze gebruikt worden.

Voorwaardelijke operators

Voorwaardelijke operators verandert de weergegeven waarde naargelang een variabele bestaat, leeg is of een waarde bevat. Zo kan de waarde, een standaard waarde, een alternatieve waarde of een foutmelding weergegeven worden of de variabele zelf een andere waarde krijgen.

Schrijfwijze Var. bestaat niet var="" var="gnu"
${var-default} default gnu
${var:-default} default default gnu
${var+alternate} alternate alternate
${var:+alternate} alternate
${var?error} error gnu
${var:?error} error error gnu

De = en := operators komen overeen met - en :-, maar de = operatoren geven de weergegeven waarde ook door aan de variabele zelf.

Als voorbeeld openen we een bestand opgeslagen in de variabele OUT_FILE met de editor opgeslagen in de variabele EDITOR. Als de variabele EDITOR en/of OUT_FILE niet bestaat, heb je een probleem. Met voorwaardelijke operatoren kunnen we dit opvangen:

dany@pindabook:~> EDITOR=$(which joe)
dany@pindabook:~> echo ${EDITOR}
/usr/bin/joe
dany@pindabook:~> echo ${EDITOR:-$(which nano)}
/usr/bin/joe
dany@pindabook:~> unset EDITOR
dany@pindabook:~> echo ${EDITOR:-$(which nano)}
/usr/bin/nano

Substring

Om een gedeelte van een tekenreeksvariabele (string) weer te geven, kan je een positie (en eventueel een lengte) opgeven of via een patroon gedeelten verwijderen. Vanaf Bash 4.2 mag je negatieve posities opgeven, deze beginnen dan te tellen vanaf het einde van de tekenreeks. Om verwarring te vermijden met voorwaardelijke default operators plaats je een negatieve positie tussen haken.

dany@pindabook:~> locatie="BE 8000"
dany@pindabook:~> echo "Postcode: ${locatie:3}"
Postcode: 8000
dany@pindabook:~> echo "Postcode: ${locatie:(-4)}"
Postcode: 8000
dany@pindabook:~> echo "Landcode: ${locatie:0:2}"
Landcode: BE

Ook met een patroon (pattern) kan je kan je een deel van de tekens beginnend vanaf links (# en ##) of rechts (% en %%) van de tekenreeks verwijderen. Met een enkel # of % wordt gestopt bij het eerste herkende patroon, bij dubbele # en % wordt doorgezocht naar het laatste voorkomende patroon (greedy).

var="open source"
Schrijfwijze positie is 5
lengte is 4
${var:positie} source
${var:positie:lengte} sour
patroon is *o?
${var#patroon} en source
${var##patroon} rce
patroon is ?e*
${var%patroon} open sour
${var%%patroon} 0

Een patroon kan je samenstellen met de volgende onderdelen: * komt overeen met geen of verschillende willekeurige tekens, ? komt overeen met juist één willekeurig teken, [...] komt overeen met één teken dat tussen de rechte haken is opgesomd, ^ zorgt voor een negatie (tegenovergestelde van hetgeen vermeld is) en posix character classes (voorgedefinieerde verzamelingen met tekens) zoals [[:alnum:]]. Door gebruik te maken van patronen kan je een gedeelde van een tekenreeks afzonderen zonder dat je de exacte positie kent.

dany@pindabook:~> echo $PATH
/home/dany/bin:/usr/local/bin:/usr/bin:/bin:/usr/lib/mit/sbin
dany@pindabook:~> echo "Laagste prioriteit in PATH: ${PATH##*:}"
Laagste prioriteit in PATH: /usr/lib/mit/sbin
dany@pindabook:~> echo "Alles uitgezonderd de laagste prioriteit: ${PATH%:*}"
Alles uitgezonderd de laagste prioriteit: /home/dany/bin:/usr/local/bin:/usr/bin:/bin
dany@pindabook:~> echo "Hoogste prioriteit in PATH: ${PATH%%:*}"
Hoogste prioriteit in PATH: /home/dany/bin

Vervangen

Patronen kan je ook gebruiken met de vervang operaties / en // gevolgd door het patroon van het te vervangen deel en de tekenreeks die in de plaats komt, telkens gescheiden door een /. Met een enkele / wordt enkel de eerste overeenkomst vervangen, met twee // alle overeenkomsten.

var="free and open"
Schrijfwijze patroon is [[:space:]]
string is _
${var/patroon/string} free_and open
${var//patroon/string} free_and_open

De veelvoud aan expansion modifiers zorgen dat je in Bash variabelen veel meer mogelijkheden hebt dan het simpelweg opslaan van waarden. Eenmaal onder de knie zorgen ze voor beknopte en expressieve scripts. Veel plezier ermee.

Parameter expansion