Loop door de regels van een bestand: Bash For Loop Uitgelegd

Ik wil door de regels van een bestand lopen met een Bash script en een van de manieren om dat te doen is met behulp van een for-lus.

Wat is een for-lus?

Een for-lus is een van de meest voorkomende programmeer constructies en het wordt gebruikt om een bepaald blok code uit te voeren, gegeven een set items in een lijst. Stel bijvoorbeeld dat je een programma wilt schrijven dat het aantal inwoners van de 10 grootste Europese steden aangeeft. Het programma kan een for-lus gebruiken om door elke stad in de lijst te gaan en het aantal mensen voor die stad af te drukken.

De uitgevoerde logica is elke keer hetzelfde en het enige dat verandert is de stad.

Hieronder ziet u de algemene syntaxis voor een Bash for-lus:

for item in do command1 command2 ... commandNdone

LIST kan bijvoorbeeld zijn:

  • een reeks getallen.
  • een reeks strings gescheiden door spaties.
  • de uitvoer van een Linux commando (bijvoorbeeld het ls commando).

De N commando’s tussen do en done worden uitgevoerd voor elk item in de lijst.

For Loop in Bash

In dit artikel leert u hoe u de for loop in Bash kunt gebruiken en specifiek om door de regels van een bestand te gaan.

Maar waarom zou je dat doen? Door de regels van een bestand gaan?

U zou dat bijvoorbeeld kunnen doen als u gegevens uit een toepassing naar een bestand hebt geëxporteerd en u die gegevens op de een of andere manier wilt uitwerken.

In dit voorbeeld gebruiken we een eenvoudig .txt-bestand waarin elke regel bevat:

  • de naam van een stad
  • het aantal mensen dat in die stad woont.

Hieronder ziet u de opmaak van het tekstbestand, een dubbele punt wordt gebruikt om elke stad te scheiden van het aantal mensen dat in die stad woont:

Istanbul:15,067,724Moscow:12,615,279London:9,126,366... 

Dus, hoe kunnen we een Bash for-lus gebruiken om door de inhoud van dit bestand te gaan?

Eerst slaan we de naam van het bestand op in een variabele

FILENAME="european-cities.txt"

Daarna gebruiken we een andere variabele en het commando cat om alle regels in het bestand te krijgen:

LINES=$(cat $FILENAME)

Hier gebruiken we commandosubstitutie om de uitvoer van het commando cat aan de LINES-variabelen toe te wijzen.

Eindelijk maakt de for-lus het mogelijk om elke regel van het bestand te doorlopen:

for LINE in $LINESdo echo "$LINE"done

Do en done worden gebruikt om de commando’s te definiëren die bij elke iteratie van de for-lus moeten worden uitgevoerd.

Bijv. een bestand met 10 regels zal de for-lus 10 iteraties doorlopen en bij elke iteratie een regel van het bestand lezen.

Het echo-commando kan worden vervangen door een willekeurige reeks commando’s, afhankelijk van wat u met elke regel in het bestand wilt doen.

Hier is het uiteindelijke script:

#!/bin/bash FILENAME="european-cities.txt"LINES=$(cat $FILENAME)for LINE in $LINESdo echo "$LINE"done

En de uitvoer van het script is…

./cities.sh Istanbul:15,067,724Moscow:12,615,279London:9,126,366Saint-Petersburg:5,383,890Berlin:3,748,148Kyiv:3,703,100Madrid:3,223,334Rome:2,857,321Paris:2,140,526Bucharest:2,106,144

We geven de lijst door aan de for-lus met behulp van het cat commando.

Dit betekent dat we alle commando’s kunnen gebruiken die we willen om de LIJST te genereren die aan de for-lus wordt doorgegeven.

Heb je nog andere mogelijke commando’s in gedachten?

Ook is de for-lus niet de enige optie om een lus in een Bash-script te maken, een andere optie is een while-lus.

Wat is een teller in een Bash for-lus?

In een for-lus kunt u ook een variabele definiëren die teller heet. U kunt een teller gebruiken om elke iteratie van de lus te volgen.

Het gebruik van een teller is heel gebruikelijk in alle programmeertalen. Het kan ook worden gebruikt om toegang te krijgen tot de elementen van een datastructuur binnen de lus (dit is niet het geval in ons voorbeeld).

Laten we het vorige programma wijzigen en een teller definiëren waarvan de waarde bij elke iteratie wordt afgedrukt:

#!/bin/bash FILENAME="european-cities.txt"LINES=$(cat $FILENAME)COUNTER=0for LINE in $LINESdo echo "Counter $COUNTER: $LINE" COUNTER=$((COUNTER+1))done

Zoals u kunt zien heb ik een variabele met de naam COUNTER gedefinieerd buiten de for-lus met de beginwaarde ingesteld op 0.

Daarna print ik bij elke iteratie de waarde van de teller samen met de regel uit het bestand.

Daarna gebruik ik de Bash rekenkundige operator om de waarde van de variabele COUNTER met 1 te verhogen.

En hier is de uitvoer van het script:

Counter 0: Istanbul:15,067,724Counter 1: Moscow:12,615,279Counter 2: London:9,126,366Counter 3: Saint-Petersburg:5,383,890Counter 4: Berlin:3,748,148Counter 5: Kyiv:3,703,100Counter 6: Madrid:3,223,334Counter 7: Rome:2,857,321Counter 8: Paris:2,140,526Counter 9: Bucharest:2,106,144

Break en Continue in een Bash For Loop

Er zijn manieren om de normale stroom van een for-lus in Bash te veranderen.

De twee statements die dat mogelijk maken zijn break en continue:

  • break: onderbreekt de uitvoering van de for-lus en springt naar de eerste regel na de for-lus.
  • doorgaan: springt naar de volgende iteratie van de for-lus.

Als we een teller hebben gedefinieerd, kunnen we zien wat er gebeurt als we break of doorgaan toevoegen aan ons bestaande script.

Laten we beginnen met break…

Ik zal een if-statement toevoegen op basis van de waarde van de teller. De break-instructie in de if breekt de uitvoering van de lus als de teller gelijk is aan 3:

#!/bin/bash FILENAME="european-cities.txt"LINES=$(cat $FILENAME)COUNTER=0for LINE in $LINESdo if ; then break fi echo "Counter $COUNTER: $LINE" COUNTER=$((COUNTER+1))done

En de uitvoer is:

Counter 0: Istanbul:15,067,724Counter 1: Moscow:12,615,279Counter 2: London:9,126,366

Zoals je kunt zien stopt de break-instructie de uitvoering van de for-lus voordat het echo commando wordt bereikt omdat COUNTER 3 is.

Daarna, laten we break vervangen door continue en kijken wat er gebeurt. Ik laat de rest van de code ongewijzigd.

#!/bin/bash FILENAME="european-cities.txt"LINES=$(cat $FILENAME)COUNTER=0for LINE in $LINESdo if ; then continue fi echo "Counter $COUNTER: $LINE" COUNTER=$((COUNTER+1))done

En hier is de uitvoer van het script:

Counter 0: Istanbul:15,067,724Counter 1: Moscow:12,615,279Counter 2: London:9,126,366

Raar…de uitvoer is hetzelfde. Waarom?

Dat komt omdat wanneer de waarde van de COUNTER 3 is, het continue commando naar de volgende iteratie van de lus springt, maar de waarde van de teller niet verhoogt.

Dus bij de volgende iteratie is de waarde van de COUNTER nog steeds 3 en het continue commando wordt opnieuw uitgevoerd, en zo verder voor alle andere iteraties.

Om dit op te lossen moeten we de waarde van de variabele COUNTER binnen het if-statement verhogen:

#!/bin/bash FILENAME="european-cities.txt"LINES=$(cat $FILENAME)COUNTER=0for LINE in $LINESdo if ; then COUNTER=$((COUNTER+1)) continue fi echo "Counter $COUNTER: $LINE" COUNTER=$((COUNTER+1))done

Deze keer zien we de juiste uitvoer:

Counter 0: Istanbul:15,067,724Counter 1: Moscow:12,615,279Counter 2: London:9,126,366Counter 4: Berlin:3,748,148Counter 5: Kyiv:3,703,100Counter 6: Madrid:3,223,334Counter 7: Rome:2,857,321Counter 8: Paris:2,140,526Counter 9: Bucharest:2,106,144

Zoals u kunt zien “Teller 3: ….” wordt niet in de terminal afgedrukt.

Het schrijven van een for-lus in één regel

Voordat we deze tutorial afsluiten, laten we eens kijken hoe we een for-lus in één regel kunnen schrijven.

Dit is geen aanbevolen praktijk, omdat het je code minder leesbaar maakt.

Maar het is goed om te weten hoe je een lus in één regel schrijft, het geeft meer diepgang aan je Bash-kennis.

De algemene syntaxis voor een Bash for-lus in één regel is de volgende:

for i in ; do ; done

Laten we de inhoud van ons tekstbestand afdrukken met een for-lus in één regel:

#!/bin/bashFILENAME="european-cities.txt"LINES=$(cat $FILENAME)for LINE in $LINES; do echo $LINE; done

Om dingen te vereenvoudigen heb ik de COUNTER en de if-instructie verwijderd. Als ze er wel waren, zou de éénregelige for-lus een stuk moeilijker te lezen zijn.

Probeer weg te blijven van oneliners als ze je code moeilijk leesbaar maken.

Conclusie

Tot slot, in deze tutorial heb je geleerd hoe je:

  1. De regels van een bestand in een variabele opslaat
  2. Een for-lus gebruikt om elke regel te doorlopen.
  3. Gebruik een teller in een for-lus.
  4. Verander de flow van een lus met break en continue.
  5. Schrijf een for-lus in één regel.

Bent dat zinvol?

Hoe ga je dit gebruiken?

Laat het me weten 🙂

Als je meer wilt leren over lussen in Bash scripting kijk dan eens naar deze tutorial.

Gerelateerde GRATIS Cursus: Ontcijfer Bash Scripting

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.