Cum să analizați datele CSV în Bash

Publicat: 2022-09-16
Jane Kelly/Shutterstock.com

Fișierele cu valori separate prin virgulă (CSV) sunt unul dintre cele mai comune formate pentru datele exportate. Pe Linux, putem citi fișiere CSV folosind comenzile Bash. Dar poate deveni foarte complicat, foarte repede. Vom da o mână de ajutor.

Ce este un fișier CSV?

Un fișier cu valori separate prin virgulă este un fișier text care conține date tabulate. CSV este un tip de date delimitate. După cum sugerează și numele, o virgulă „ , ” este folosită pentru a separa fiecare câmp de date – sau valoare – de vecinii săi.

Ce este un fișier CSV și cum îl deschid?
RELATE Ce este un fișier CSV și cum îl deschid?

CSV este peste tot. Dacă o aplicație are funcții de import și export, aproape întotdeauna va accepta CSV. Fișierele CSV pot fi citite de om. Puteți să vă uitați în interiorul lor cu mai puțin, să le deschideți în orice editor de text și să le mutați de la program la program. De exemplu, puteți exporta datele dintr-o bază de date SQLite și le puteți deschide în LibreOffice Calc.

Cu toate acestea, chiar și CSV poate deveni complicat. Doriți să aveți o virgulă într-un câmp de date? Câmpul respectiv trebuie să aibă ghilimele „ " ” înconjurate. Pentru a include ghilimele într-un câmp, fiecare ghilimele trebuie introdus de două ori.

Desigur, dacă lucrați cu CSV generat de un program sau script pe care l-ați scris, este probabil ca formatul CSV să fie simplu și direct. Dacă ești forțat să lucrezi cu formate CSV mai complexe, Linux fiind Linux, există soluții pe care le putem folosi și pentru asta.

Câteva date eșantion

Puteți genera cu ușurință câteva exemple de date CSV, folosind site-uri precum Generatorul de date online. Puteți defini câmpurile dorite și alegeți câte rânduri de date doriți. Datele dvs. sunt generate folosind valori fictive realiste și descărcate pe computer.

Am creat un fișier care conține 50 de rânduri de informații false ale angajaților:

  • id : O valoare întreagă unică simplă.
  • prenume : prenumele persoanei.
  • lastname : Numele de familie al persoanei.
  • job-title : titlul postului persoanei.
  • email-address : adresa de e-mail a persoanei.
  • ramură : filiala companiei în care lucrează.
  • stare : statul în care se află sucursala.

Unele fișiere CSV au o linie de antet care listează numele câmpurilor. Fișierul nostru exemplu are unul. Iată partea de sus a fișierului nostru:

Exemplul de fișier CSV

Prima linie conține numele câmpurilor ca valori separate prin virgulă.

Analizarea datelor din fișierul CSV

Să scriem un script care va citi fișierul CSV și va extrage câmpurile din fiecare înregistrare. Copiați acest script într-un editor și salvați-l într-un fișier numit „field.sh”.

 #! /bin/bash

în timp ce IFS="," citește -r id prenume prenume titlu job e-mail stare ramură
do
  echo „ID înregistrare: $id”
  echo "Prenumele: $prenume"
  echo " Nume: $nume"
  echo „Titlul postului: $jobtitle”
  echo "Adăugați e-mail: $email"
  echo " Ramura: $ramură"
  echo " Stare: $state"
  ecou ""
terminat < <(coada -n +2 sample.csv)

Există destul de mult în micul nostru scenariu. Să-l descompunem.

Cum să procesați un fișier linie cu linie într-un script Linux Bash
LEGATE Cum să procesați un fișier linie cu linie într-un script Linux Bash

Folosim o buclă while . Atâta timp cât condiția buclei while se rezolvă la adevărat, corpul buclei while va fi executat. Corpul buclei este destul de simplu. O colecție de instrucțiuni echo sunt folosite pentru a imprima valorile unor variabile în fereastra terminalului.

Condiția buclei while este mai interesantă decât corpul buclei. Precizăm că trebuie folosită o virgulă ca separator de câmp intern, cu instrucțiunea IFS="," . IFS este o variabilă de mediu. Comanda de read se referă la valoarea sa atunci când parsează secvențe de text.

Folosim opțiunea -r (reține barele oblice inverse) a comenzii de read pentru a ignora orice bare oblice inverse care ar putea fi în date. Vor fi tratați ca personaje obișnuite.

Textul pe care îl parsează comanda de read este stocat într-un set de variabile numite după câmpurile CSV. La fel de ușor ar fi putut fi numite câmp1, field1, field2, ... field7 , dar numele semnificative fac viața mai ușoară.

Datele sunt obținute ca rezultat din comanda tail . Folosim tail deoarece ne oferă o modalitate simplă de a sări peste linia antetului fișierului CSV. Opțiunea -n +2 (numărul liniei) îi spune lui tail să înceapă să citească la rândul numărul doi.

Construcția <(...) se numește substituție de proces. Determină Bash să accepte rezultatul unui proces ca și cum ar proveni dintr-un descriptor de fișier. Acesta este apoi redirecționat în bucla while , furnizând textul pe care comanda de read îl va analiza.

Faceți scriptul executabil folosind comanda chmod . Va trebui să faceți acest lucru de fiecare dată când copiați un script din acest articol. Înlocuiți numele scriptului corespunzător în fiecare caz.

 chmod +x field.sh 

Realizarea unui script executabil cu chmod

Când rulăm scriptul, înregistrările sunt împărțite corect în câmpurile lor constitutive, fiecare câmp stocat într-o variabilă diferită.

 ./câmp.sh 

Fișierul CSV analizat de scriptul field.sh.

Fiecare înregistrare este tipărită ca un set de câmpuri.

Selectarea Câmpurilor

Poate că nu vrem sau nu trebuie să recuperăm fiecare câmp. Putem obține o selecție de câmpuri prin încorporarea comenzii cut .

Acest script se numește „select.sh”.

 #!/bin/bash

în timp ce IFS="," citește -r id jobtitle stare de ramură
do
  echo „ID înregistrare: $id”
  echo „Titlul postului: $jobtitle”
  echo " Ramura: $ramură"
  echo " Stare: $state"
  ecou ""
terminat < <(cut -d "," -f1,4,6,7 sample.csv | coada -n +2)

Am adăugat comanda cut în clauza de înlocuire a procesului. Folosim opțiunea -d (delimitator) pentru a spune cut să folosească virgulele „ , ” ca delimitator. Opțiunea -f (câmp) spune cut că vrem câmpurile unu, patru, șase și șapte. Aceste patru câmpuri sunt citite în patru variabile, care sunt imprimate în corpul buclei while .

Aceasta este ceea ce obținem când rulăm scriptul.

 ./select.sh 

Analizarea fișierului CSV cu field.sh pentru a extrage o selecție specifică de câmpuri

Adăugând comanda cut , putem să selectăm câmpurile pe care le dorim și să le ignorăm pe cele pe care nu le facem.

Până acum, bine. Dar…

Dacă CSV-ul cu care vă ocupați este simplu, fără virgule sau ghilimele în datele de câmp, ceea ce am acoperit probabil va satisface nevoile dvs. de analiză CSV. Pentru a arăta problemele pe care le putem întâlni, am modificat un mic eșantion de date pentru a arăta astfel.

 id, prenume, prenume, titlul postului, adresă de e-mail, sucursală, stat
1, Rosalyn, Brennan, „Steward, Senior”, [email protected], Minneapolis, Maryland
2,Danny,Redden,"Analist ""Buget""",[email protected], Venice, Carolina de Nord
3, Lexi, Roscoe, Farmacist, Irlington, Vermont
  • Înregistrarea unu are o virgulă în câmpul job-title , așa că câmpul trebuie să fie împachetat între ghilimele.
  • Înregistrarea doi are un cuvânt înfășurat în două seturi de ghilimele în câmpul jobs-title postului.
  • Înregistrarea trei nu are date în câmpul email-address .

Aceste date au fost salvate ca „sample2.csv”. Modificați scriptul „field.sh” pentru a apela „sample2.csv” și salvați-l ca „field2.sh”.

 #! /bin/bash

în timp ce IFS="," citește -r id prenume prenume titlu job e-mail stare ramură
do
  echo „ID înregistrare: $id”
  echo "Prenumele: $prenume"
  echo " Nume: $nume"
  echo „Titlul postului: $jobtitle”
  echo "Adăugați e-mail: $email"
  echo " Ramura: $ramură"
  echo " Stare: $state"
  ecou ""
terminat < <(coada -n +2 sample2.csv)

Când rulăm acest script, putem vedea fisuri care apar în analizatorii CSV simpli.

 ./field2.sh 

Rularea câmpului2.sh

Prima înregistrare împarte câmpul cu titlul postului în două câmpuri, tratând a doua parte drept adresa de e-mail. Fiecare câmp după aceasta este mutat cu un loc la dreapta. Ultimul câmp conține atât valorile de branch , cât și de state .

O înregistrare cu un câmp împărțit în două câmpuri

A doua înregistrare păstrează toate ghilimelele. Ar trebui să aibă doar o singură pereche de ghilimele în jurul cuvântului „Buget”.

O înregistrare cu ghilimele manipulate greșit

A treia înregistrare tratează de fapt câmpul lipsă așa cum ar trebui. Adresa de e-mail lipsește, dar totul este așa cum ar trebui.

O înregistrare cu un câmp lipsă, care este tratată corect

În mod contraintuitiv, pentru un format de date simplu, este foarte dificil să scrieți un parser CSV general robust. Instrumente precum awk vă vor permite să vă apropiați, dar există întotdeauna cazuri marginale și excepții care se strecoară.

Cum să utilizați comanda awk pe Linux
LEGATE Cum să utilizați comanda awk pe Linux

Încercarea de a scrie un parser CSV infailibil nu este probabil cea mai bună cale de urmat. O abordare alternativă – mai ales dacă lucrați la un anumit termen limită – folosește două strategii diferite.

Una este să utilizați un instrument conceput special pentru a vă manipula și extrage datele. Al doilea este să vă igienizați datele și să înlocuiți scenariile cu probleme, cum ar fi virgulele încorporate și ghilimelele. Parserii dvs. simpli Bash pot face față apoi CSV-ului prietenos cu Bash.

Setul de instrumente csvkit

Setul de instrumente CSV csvkit este o colecție de utilitare creată în mod expres pentru a ajuta la lucrul cu fișierele CSV. Va trebui să îl instalați pe computer.

Pentru a-l instala pe Ubuntu, utilizați această comandă:

 sudo apt install csvkit 

Instalarea csvkit pe Ubuntu

Pentru a-l instala pe Fedora, trebuie să tastați:

 sudo dnf install python3-csvkit 

Instalarea csvkit pe Fedora

Pe Manjaro comanda este:

 sudo pacman -S csvkit 

Instalarea csvkit pe Manjaro

Dacă îi transmitem numele unui fișier CSV, utilitarul csvlook afișează un tabel care arată conținutul fiecărui câmp. Conținutul câmpului este afișat pentru a arăta ce reprezintă conținutul câmpului, nu așa cum este stocat în fișierul CSV.

Să încercăm csvlook cu fișierul nostru problematic „sample2.csv”.

 csvlook sample2.csv 

CSV supărător analizat corect de csvlook

Toate câmpurile sunt afișate corect. Acest lucru demonstrează că problema nu este CSV. Problema este că scripturile noastre sunt prea simpliste pentru a interpreta CSV-ul corect.

Pentru a selecta anumite coloane, utilizați comanda csvcut . Opțiunea -c (coloană) poate fi utilizată cu nume de câmpuri sau numere de coloane sau o combinație a ambelor.

Să presupunem că trebuie să extragem numele și prenumele, titlurile postului și adresele de e-mail din fiecare înregistrare, dar dorim să avem ordinea numelui ca „nume, prenume”. Tot ce trebuie să facem este să punem numele câmpurilor sau numerele în ordinea dorită.

Aceste trei comenzi sunt toate echivalente.

 csvcut -c nume, prenume, titlul postului, adresa de e-mail sample2.csv
 csvcut -c nume, prenume,4,5 sample2.csv
 csvcut -c 3,2,4,5 sample2.csv 

Alegerea câmpurilor într-o ordine preferată cu csvcut

Putem adăuga comanda csvsort pentru a sorta rezultatul după un câmp. Folosim opțiunea -c (coloană) pentru a specifica coloana după care să sortăm și opțiunea -r (invers) pentru a sorta în ordine descrescătoare.

 csvcut -c 3,2,4,5 sample2.csv | csvsort -c 1 -r 

Alegerea câmpurilor și sortarea lor după o singură coloană

Pentru a face ieșirea mai frumoasă, o putem alimenta prin csvlook .

 csvcut -c 3,2,4,5 sample2.csv | csvsort -c 1 -r | csvlook 

Folosind csvlook pentru a imprima destul de mult selecția sortată de câmpuri

O notă bună este că, deși înregistrările sunt sortate, linia antetului cu numele câmpurilor este păstrată ca primă linie. Odată ce suntem fericiți că avem datele așa cum le dorim, putem elimina csvlook din lanțul de comandă și putem crea un nou fișier CSV redirecționând rezultatul într-un fișier.

Am adăugat mai multe date la „sample2.file”, am eliminat comanda csvsort și am creat un nou fișier numit „sample3.csv”.

 csvcut -c 3,2,4,5 sample2.csv > sample3.csv 

O modalitate sigură de a igieniza datele CSV

Dacă deschideți un fișier CSV în LibreOffice Calc, fiecare câmp va fi plasat într-o celulă. Puteți utiliza funcția de căutare și înlocuire pentru a căuta virgule. Le puteți înlocui cu „nimic”, astfel încât să dispară, sau cu un caracter care să nu afecteze analiza CSV, cum ar fi un punct și virgulă „ ; " de exemplu.

Nu veți vedea ghilimele în jurul câmpurilor citate. Singurele ghilimele pe care le veți vedea sunt ghilimelele încorporate în datele câmpului. Acestea sunt afișate ca ghilimele simple. Găsirea și înlocuirea acestora cu un singur apostrof „ ' ” va înlocui ghilimelele duble din fișierul CSV.

Folosind opțiunea de căutare și înlocuire a LibreOffice Calc pentru a înlocui ghilimelele cu apostrofe

Găsirea și înlocuirea într-o aplicație precum LibreOffice Calc înseamnă că nu puteți șterge accidental niciuna dintre virgulele separatoare de câmpuri și nici nu puteți șterge ghilimelele din jurul câmpurilor citate. Veți modifica doar valorile datelor din câmpuri.

Am schimbat toate virgulele din câmpurile cu punct și virgulă și toate ghilimelele încorporate cu apostrofe și am salvat modificările.

Fișierul CSV modificat

Apoi am creat un script numit „field3.sh” pentru a analiza „sample3.csv”.

 #! /bin/bash

în timp ce IFS="," citește -r nume prenume titlu job e-mail
do
  echo " Nume: $nume"
  echo "Prenumele: $prenume"
  echo „Titlul postului: $jobtitle”
  echo "Adăugați e-mail: $email"
  ecou ""
terminat < <(coada -n +2 sample3.csv)

Să vedem ce obținem când îl rulăm.

 ./field3.sh 

O secțiune de CSV analizat corect

Analizatorul nostru simplu poate gestiona acum înregistrările noastre anterior problematice.

Veți vedea o mulțime de CSV

CSV este, fără îndoială, cel mai apropiat lucru de o limbă comună pentru datele aplicației. Majoritatea aplicațiilor care gestionează o anumită formă de date acceptă importul și exportul CSV. A ști cum să gestionezi CSV-ul într-un mod realist și practic-ți va fi de folos.

LEGATE: 9 exemple de script Bash pentru a începe pe Linux