Bucla prin liniile unui fișier: Bash For Loop Explained

Vreau să parcurg liniile unui fișier în buclă cu un script Bash și una dintre modalitățile de a face acest lucru este să folosesc o buclă for.

Ce este o buclă for?

O buclă for este una dintre cele mai comune construcții de programare și este folosită pentru a executa un anumit bloc de cod având în vedere un set de elemente dintr-o listă. De exemplu, să spunem că doriți să scrieți un program care să tipărească numărul de persoane care locuiesc în cele mai mari 10 orașe europene. Programul poate folosi o buclă for pentru a trece prin fiecare oraș din listă și a tipări numărul de persoane pentru acel oraș.

Logica executată este de fiecare dată aceeași și singurul lucru care se schimbă este orașul.

Mai jos puteți vedea sintaxa generică pentru o buclă for Bash:

for item in do command1 command2 ... commandNdone

LISTA poate fi, de exemplu:

  • un interval de numere.
  • o secvență de șiruri de caractere separate prin spații.
  • ieșirea unei comenzi Linux (de exemplu, comanda ls).

Cele N comenzi dintre do și done sunt executate pentru fiecare element din listă.

For Loop în Bash

În acest articol veți învăța cum să folosiți bucla for în Bash și în special pentru a parcurge liniile unui fișier.

Dar de ce ați face asta? Să parcurgeți liniile unui fișier?

De exemplu, ați putea avea nevoie să faceți asta dacă ați exportat date dintr-o aplicație într-un fișier și doriți să elaborați cumva acele date.

În acest exemplu vom folosi un simplu fișier .txt în care fiecare linie conține:

  • numele unui oraș
  • numărul de persoane care locuiesc în acel oraș.

Mai jos puteți vedea formatul fișierului text, se folosesc două puncte pentru a separa fiecare oraș de numărul de persoane care locuiesc în acel oraș:

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

Atunci, cum putem folosi o buclă Bash for loop pentru a parcurge conținutul acestui fișier?

Prima dată vom stoca numele fișierului într-o variabilă

FILENAME="european-cities.txt"

După aceea, vom folosi o altă variabilă și comanda cat pentru a obține toate liniile din fișier:

LINES=$(cat $FILENAME)

Aici folosim substituirea comenzii pentru a atribui ieșirea comenzii cat la variabilele LINES.

În cele din urmă, bucla for permite parcurgerea fiecărei linii din fișier:

for LINE in $LINESdo echo "$LINE"done

Do și done sunt folosite pentru a defini comenzile care vor fi executate la fiecare iterație a buclei for.

De exemplu, dacă aveți un fișier cu 10 linii, bucla for va trece prin 10 iterații și la fiecare iterație va citi o linie din fișier.

Comanda echo poate fi înlocuită cu orice secvență de comenzi în funcție de ceea ce doriți să faceți cu fiecare linie din fișier.

Iată scriptul final:

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

Și ieșirea scriptului este…

./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

Pasăm lista către bucla for folosind comanda cat.

Acest lucru înseamnă că putem folosi orice comenzi dorim pentru a genera LISTA care să fie trecută în bucla for.

Vă gândiți la alte comenzi posibile?

De asemenea, bucla for nu este singura opțiune pentru a crea o buclă într-un script Bash, o altă opțiune este o buclă while.

Ce este un contor într-o buclă for Bash?

Într-o buclă for se poate defini și o variabilă numită counter. Puteți folosi un contor pentru a urmări fiecare iterație a buclei.

Utilizarea unui contor este foarte comună în toate limbajele de programare. De asemenea, poate fi folosit pentru a accesa elementele unei structuri de date în interiorul buclei (nu este cazul în exemplul nostru).

Să modificăm programul anterior și să definim un contor a cărui valoare este tipărită la fiecare iterație:

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

După cum vedeți am definit o variabilă numită CONTOR în afara buclei for cu valoarea sa inițială stabilită la 0.

Apoi la fiecare iterație tipăresc valoarea contorului împreună cu linia din fișier.

După ce am făcut asta folosesc operatorul aritmetic Bash pentru a crește valoarea variabilei COUNTER cu 1.

Și iată ieșirea scriptului:

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 and Continue in a Bash For Loop

Există modalități de a modifica fluxul normal al unei bucle for în Bash.

Cele două instrucțiuni care permit acest lucru sunt break și continue:

  • break: întrerupe execuția buclei for și sare la prima linie după bucla for.
  • continue: sare la următoarea iterație a buclei for.

Având definit un contor ne ajută să vedem ce se întâmplă când adăugăm break sau continue la scriptul nostru existent.

Să începem cu break…

Voi adăuga o instrucțiune if bazată pe valoarea contorului. Instrucțiunea break din interiorul if-ului întrerupe execuția buclei dacă contorul este egal cu 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

Și ieșirea este:

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

După cum puteți vedea, instrucțiunea break oprește execuția buclei for înainte de a ajunge la comanda echo deoarece COUNTER este 3.

După aceea, să înlocuim break cu continue și să vedem ce se întâmplă. Voi lăsa restul codului neschimbat.

#!/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

Și iată rezultatul pentru script:

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

Este ciudat…rezultatul este același. De ce?

Pentru că atunci când valoarea lui COUNTER este 3, instrucțiunea continue sare la următoarea iterație a buclei, dar nu incrementează valoarea contorului.

Așa că la următoarea iterație valoarea lui COUNTER este tot 3 și se execută din nou instrucțiunea continue, și așa mai departe pentru toate celelalte iterații.

Pentru a remedia acest lucru trebuie să creștem valoarea variabilei COUNTER în interiorul instrucțiunii if:

#!/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

De data aceasta vedem ieșirea corectă:

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

După cum puteți vedea „Counter 3: ….” nu este tipărită în terminal.

Scrierea unei bucle for într-o singură linie

Înainte de a termina acest tutorial, să vedem cum putem scrie o buclă for într-o singură linie.

Aceasta nu este o practică sugerată având în vedere că vă face codul mai puțin lizibil.

Dar este bine să știți cum să scrieți o buclă într-o singură linie, dă mai multă profunzime cunoștințelor dumneavoastră despre Bash.

Sintaxa generică pentru o buclă Bash for într-o singură linie este următoarea:

for i in ; do ; done

Să imprimăm conținutul fișierului nostru text cu o buclă for pe o singură linie:

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

Pentru a simplifica lucrurile am eliminat COUNTER și instrucțiunea if. Dacă ar fi fost acolo, bucla for cu o singură linie ar fi fost mult mai greu de citit.

Încercați să stați departe de one-liners dacă vă fac codul greu de citit.

Concluzie

În concluzie, în acest tutorial ați învățat cum să:

  1. Stocați liniile unui fișier într-o variabilă
  2. Utilizați o buclă for pentru a trece prin fiecare linie.
  3. Utilizați un contor într-o buclă for.
  4. Schimbați fluxul unei bucle cu break și continue.
  5. Scrieți o buclă for într-o singură linie.

Trece sens?

Cum ai de gând să folosești acest lucru?

Dă-mi de știre 🙂

Dacă vrei să înveți mai multe despre bucle în scriptingul Bash, aruncă o privire la acest tutorial.

Curs GRATUIT înrudit: Descifrarea scriptingului Bash

.

Lasă un răspuns

Adresa ta de email nu va fi publicată.