Tips en Trucs 2023

Heredoc in Bash

Wanneer je met Bash scripts werkt, kun je in een situatie terechtkomen waarin je een reeks tekstregels moet verwerken met dezelfde opdracht. Gelukkig is er een manier in Bash om dit op een meer optimale manier te doen met HereDoc.

HereDoc, acroniem voor Here Document, is een methode voor het doorgeven van meerdere regels aan een programma of opdracht. Het concept van heredoc is niet alleen gerelateerd aan Bash. Veel populaire programmeertalen zoals Perl, Ruby en PHP ondersteunen heredoc.

Algemene vorm van HereDoc

opdracht << EOF
  Regel 1
  Regel 2
  .....
  Laatste regel
EOF

Meerdere regels weergeven

Laten we beginnen met een eenvoudig voorbeeld van het omleiden van een meerregelige tekenreeks en het afdrukken ervan in de terminal.

De opdracht cat accepteert een invoerstroom en met heredoc kun je het blok met regels omleiden om het op de terminal weer te geven.

dany@pindabook:~$ cat << EOF
> Deze tekst bestaat uit verschillende regels.
> Een gegevenstroom waarop je bewerkingen kunt uitvoeren.
> Dankzij HEREDOC.
> EOF
Deze tekst bestaat uit verschillende regels.
Een gegevenstroom waarop je bewerkingen kunt uitvoeren.
Dankzij HEREDOC.

Bij het intypen verschijnen de >-tekens automatisch om aan te duiden dat je de opdracht nog verder moet afwerken. Deze tekens verschijnen niet als je zoals in de volgende voorbeelden oude opdrachten terughaalt met de pijltoetsen omhoog en omlaag. M.a.w. typ je de opdrachten, dan zie je de >-tekens, anders niet.

We hebben drie regels die worden doorgestuurd naar de opdracht cat. We gebruiken EOF als scheidingsteken. Je kunt echter alles gebruiken wat je wilt, maar houd het begin- en eindpunt identiek.

dany@pindabook:~$ wc -l << BLK
Deze tekst bestaat uit verschillende regels.
Een gegevenstroom waarop je bewerkingen kunt uitvoeren.
Dankzij HEREDOC.
BLK
3

Omleiden en afvoeren in HereDoc

Je kunt de uitvoer omleiding operator (>) combineren met heredoc en de uitvoer omleiden naar een bestand in plaats van het af te drukken in de terminal.

We gebruiken hetzelfde voorbeeld als daarstraks en sturen de uitvoer door naar het bestand met de naam heredoc.txt.

dany@pindabook:~$ cat << EOF > heredoc.txt
Deze tekst bestaat uit verschillende regels.
Een gegevenstroom waarop je bewerkingen kunt uitvoeren.
Dankzij HEREDOC.
EOF

De uitvoer van heredoc kan doorgestuurd (pipe |) worden voor verdere verwerking.

dany@pindabook:~$ cat << EOF | grep -i HEREDOC
Deze tekst bestaat uit verschillende regels.
Een gegevenstroom waarop je bewerkingen kunt uitvoeren.
Dankzij HEREDOC.
EOF
Dankzij HEREDOC.

Witruimte in HereDoc

Witruimtes zoals spaties worden in heredoc behouden, waardoor je heredoc ook kunt gebruiken om regels te laten inspringen.

dany@pindabook:~$ cat << EOF                  
Deze tekst bestaat uit verschillende regels.
Een gegevenstroom waarop je bewerkingen kunt uitvoeren.
   Dankzij HEREDOC.
EOF
Deze tekst bestaat uit verschillende regels.
Een gegevenstroom waarop je bewerkingen kunt uitvoeren.
   Dankzij HEREDOC.

Variabele en opdrachtuitbreiding in HereDoc

Het is niet zo dat je alleen tekenreeksen kunt doorgeven binnen het HereDoc blok. Je kunt door de gebruiker gedefinieerde variabelen en omgevingsvariabelen doorgeven en opdrachten uitvoeren binnen het blok.

Kijk eens naar het onderstaande voorbeeld. Binnen het blok, hebben we een door de gebruiker gedefinieerde variabele ${AUTEUR}, een omgevingsvariabele ${SHELL}, een externe opdracht whoami.

Wanneer dit fragment wordt verzonden, worden de variabelen en opdrachten uitgebreid en vervolgens wordt het doorgestuurd naar de cat opdracht.

dany@pindabook:~$ AUTEUR="PindaNet"
dany@pindabook:~$ cat << EOF
> Auteur: ${AUTEUR}               # Zelf gedefinieerde variabele
> Tip: Bash Heredoc
> Ik gebruik de ${SHELL} terminal # Omgevings variabele
> $(whoami)                       # Uitvoer opdracht
> EOF
Auteur: PindaNet               # Zelf gedefinieerde variabele
Tip: Bash Heredoc
Ik gebruik de /bin/bash terminal # Omgevings variabele
dany                       # Uitvoer opdracht
Heredoc

Je kunt de begin delimiter omsluiten met enkele aanhalingstekens om de uitbreiding binnen het blok te onderdrukken. Op deze manier wordt alles binnen het blok behandeld als een letterlijke tekenreeks.

dany@pindabook:~$ cat << 'EOF'
Auteur: ${AUTEUR}               # Zelf gedefinieerde variabele
Tip: Bash Heredoc
Ik gebruik de ${SHELL} terminal # Omgevings variabele
$(whoami)                       # Uitvoer opdracht
EOF
Auteur: ${AUTEUR}               # Zelf gedefinieerde variabele
Tip: Bash Heredoc
Ik gebruik de ${SHELL} terminal # Omgevings variabele
$(whoami)                       # Uitvoer opdracht

Commentaar van meerdere regels met HereDoc

Zoals je misschien al weet, ondersteunt Bash geen commentaar van meerdere regels. Met hereedoc kun je meerregelig commentaar maken door het blok om te leiden naar het no-op opdracht (:).

De no-op is een in Bash ingebouwde opdracht die de invoer aanneemt en nul teruggeeft. Je kunt dit zien als een synoniem voor de eveneens in bash ingebouwde true opdracht die ook nul teruggeeft.

dany@pindabook:~$ : << 'COMMENTAAR'
> Auteur: PindaNet
> Tip: Bash Heredoc
> Bash versie: 5.2.15
> OS: Debian 12 Bookworm
> COMMENTAAR

Speciale tekens escapen in HereDoc

HereDoc blokken kunnen speciale tekens bevatten. Als je de speciale tekens wilt omzeilen, zijn er een paar manieren om dit voor elkaar te krijgen.

Je kunt het scheidingsteken omsluiten met enkele of dubbele aanhalingstekens of een backslash vooraf laten gaan aan het scheidingsteken. Op deze manier worden alle speciale tekens geëscaped.

dany@pindabook:~$ cat << 'EOF'
Ik gebruik de ${SHELL} terminal # Omgevings variabele
$(whoami)                       # Uitvoer opdracht
EOF                                               
Ik gebruik de ${SHELL} terminal # Omgevings variabele
$(whoami)                       # Uitvoer opdracht
dany@pindabook:~$ cat << "EOF"
Ik gebruik de ${SHELL} terminal # Omgevings variabele
$(whoami)                       # Uitvoer opdracht
EOF
Ik gebruik de ${SHELL} terminal # Omgevings variabele
$(whoami)                       # Uitvoer opdracht
dany@pindabook:~$ cat << \EOF
Ik gebruik de ${SHELL} terminal # Omgevings variabele
$(whoami)                       # Uitvoer opdracht
EOF
Ik gebruik de ${SHELL} terminal # Omgevings variabele
$(whoami)                       # Uitvoer opdracht

In plaats van alle speciale tekens te escapen, kun je ook bepaalde speciale tekens binnen het blok escapen door een backslash toe te voegen voor elk speciaal teken.

dany@pindabook:~$ cat << EOF
Ik gebruik de \${SHELL} terminal # Omgevings variabele
$(whoami)                       # Uitvoer opdracht
EOF
Ik gebruik de ${SHELL} terminal # Omgevings variabele
dany                       # Uitvoer opdracht

Praktische toepassing

Als je opdrachten wilt uitvoeren over een SSH verbinding, dan kun je heredoc gebruiken in combinatie met de ssh opdracht. Normaal gesproken kun je met de ssh opdracht op de volgende manier opdrachten uitvoeren op de computer op afstand.

ssh gebruiker@computernaam "opdracht"

Je moet dezelfde opdracht steeds herhalen als je meer opdrachten wilt uitvoeren op afstand. Met heredoc kun je alle opdrachten groeperen en uitvoeren.

dany@main:~$ ssh -T dany@pindabook.local << EOF
> echo -n "Datum: "
> date
> echo -n "Naam: "
> uname -n
> EOF
Linux pindabook 6.1.0-10-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.38-2 (2023-07-27) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Datum: ma 31 jul 2023 13:57:41 CEST
Naam: pindabook

Als dezelfde code op meerdere computers moet worden uitgevoerd, kun je een for-lus toevoegen samen met heredoc. Je kunt dit gebruiken om journal rapporten op verschillende computers op te vragen. In het voorbeeld gebruik ik tweemaal dezelfde computer (pindabook.local).

declare -a server=( pindabook.local pindabook.local )
for host in ${server[@]}
do
  ssh -T dany@${host} << EOF
  echo "Uitvoeren op - ${host}"
  journalctl | tail -10
EOF
done

Bij het uitvoeren van het bovenstaande script, merken we dat de opdrachten in het HereDoc blok tweemaal via een SSH verbinding op de pindabook.local computer worden uitgevoerd.

dany@main:~$ bash journalall.sh
Linux pindabook 6.1.0-10-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.38-2 (2023-07-27) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Uitvoeren op - pindabook.local
Hint: You are currently not seeing messages from other users and the system.
      Users in groups 'adm', 'systemd-journal' can see all messages.
      Pass -q to turn off this notice.
jul 31 14:22:47 pindabook wallpaper.sh[1310]: Bereik gemeten omgevingslicht: 1870
jul 31 14:22:47 pindabook wallpaper.sh[1310]: Bereik instelbare helderheid: 468
jul 31 14:22:47 pindabook wallpaper.sh[1310]: Relatief omgevingslicht: 0.04
jul 31 14:22:47 pindabook wallpaper.sh[1310]: Helderheid aanpassen van 108 naar 113
jul 31 14:22:47 pindabook wallpaper.sh[1310]: verhogen: 108
jul 31 14:22:48 pindabook wallpaper.sh[1310]: verhogen: 109
jul 31 14:22:49 pindabook wallpaper.sh[1310]: verhogen: 110
jul 31 14:22:50 pindabook wallpaper.sh[1310]: verhogen: 111
jul 31 14:22:51 pindabook wallpaper.sh[1310]: verhogen: 112
jul 31 14:22:52 pindabook wallpaper.sh[1310]: verhogen: 113
Linux pindabook 6.1.0-10-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.38-2 (2023-07-27) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Uitvoeren op - pindabook.local
Hint: You are currently not seeing messages from other users and the system.
      Users in groups 'adm', 'systemd-journal' can see all messages.
      Pass -q to turn off this notice.
jul 31 14:22:47 pindabook wallpaper.sh[1310]: Relatief omgevingslicht: 0.04
jul 31 14:22:47 pindabook wallpaper.sh[1310]: Helderheid aanpassen van 108 naar 113
jul 31 14:22:47 pindabook wallpaper.sh[1310]: verhogen: 108
jul 31 14:22:48 pindabook wallpaper.sh[1310]: verhogen: 109
jul 31 14:22:49 pindabook wallpaper.sh[1310]: verhogen: 110
jul 31 14:22:50 pindabook wallpaper.sh[1310]: verhogen: 111
jul 31 14:22:51 pindabook wallpaper.sh[1310]: verhogen: 112
jul 31 14:22:52 pindabook wallpaper.sh[1310]: verhogen: 113
jul 31 14:23:03 pindabook sshd[4158]: Received disconnect from 2a02:a03f:e02a:8901:8254:12a:d1ca:4d3f port 48196:11: disconnected by user
jul 31 14:23:03 pindabook sshd[4158]: Disconnected from user dany 2a02:a03f:e02a:8901:8254:12a:d1ca:4d3f port 48196

Bij de tweede uitvoering zie je een regel in de uitvoer waarbij je ziet dat de vorige verbinding werd verbroken (Disconnected from user dany).