
Bestanden met door komma’s gescheiden waarden (CSV) zijn een van de meest gebruikte indelingen voor geëxporteerde gegevens. Op Linux kunnen we CSV-bestanden lezen met behulp van Bash-opdrachten. Maar het kan heel ingewikkeld worden, heel snel. We helpen een handje.
Wat is een CSV-bestand?
Een bestand met door komma’s gescheiden waarden is een tekstbestand dat getabelleerde gegevens bevat. CSV is een soort gescheiden gegevens. Zoals de naam al doet vermoeden, een komma “,
” wordt gebruikt om elk gegevensveld te scheiden, of waarde– van zijn buren.
CSV is overal. Als een applicatie import- en exportfuncties heeft, ondersteunt deze bijna altijd CSV. CSV-bestanden zijn leesbaar voor mensen. Je kunt er met minder in kijken, ze openen in elke teksteditor en ze van programma naar programma verplaatsen. U kunt bijvoorbeeld de gegevens uit een SQLite-database exporteren en openen in LibreOffice Calc.
Zelfs CSV kan echter ingewikkeld worden. Wilt u een komma in een gegevensveld hebben? Dat veld moet tussen aanhalingstekens staan ”"
‘ eromheen gewikkeld. Om aanhalingstekens in een veld op te nemen, moet elk aanhalingsteken tweemaal worden ingevoerd.
Als u werkt met CSV dat is gegenereerd door een programma of script dat u hebt geschreven, is de CSV-indeling waarschijnlijk eenvoudig en ongecompliceerd. Als je gedwongen wordt om met complexere CSV-formaten te werken, waarbij Linux Linux is, zijn er ook oplossingen die we daarvoor kunnen gebruiken.
Enkele voorbeeldgegevens
U kunt eenvoudig enkele CSV-voorbeeldgegevens genereren met behulp van sites zoals Online Data Generator. U kunt de gewenste velden definiëren en kiezen hoeveel rijen met gegevens u wilt. Uw gegevens worden gegenereerd met behulp van realistische dummy-waarden en gedownload naar uw computer.
We hebben een bestand gemaakt met 50 rijen dummy-werknemersinformatie:
- ID kaart: Een eenvoudige unieke integerwaarde.
- Voornaam: De voornaam van de persoon.
- achternaam: De achternaam van de persoon.
- functietitel: De functietitel van de persoon.
- e-mailadres: Het e-mailadres van de persoon.
- Afdeling: De bedrijfstak waarin ze werken.
- staat: De staat waarin het filiaal zich bevindt.
Sommige CSV-bestanden hebben een kopregel met de veldnamen. Ons voorbeeldbestand heeft er een. Dit is de top van ons bestand:
De eerste regel bevat de veldnamen als door komma’s gescheiden waarden.
Gegevens parseren Vorm het CSV-bestand
Laten we een script schrijven dat het CSV-bestand leest en de velden uit elk record extraheert. Kopieer dit script naar een editor en sla het op in een bestand met de naam “field.sh”.
#! /bin/bash while IFS="," read -r id firstname lastname jobtitle email branch state do echo "Record ID: $id" echo "Firstname: $firstname" echo " Lastname: $lastname" echo "Job Title: $jobtitle" echo "Email add: $email" echo " Branch: $branch" echo " State: $state" echo "" done < <(tail -n +2 sample.csv)
Er zit nogal wat in ons kleine script. Laten we het opsplitsen.
We gebruiken een while
lus. Zolang de while
lus voorwaarde lost op waar, het lichaam van de while
lus wordt uitgevoerd. Het lichaam van de lus is vrij eenvoudig. Een verzameling van echo
statements worden gebruikt om de waarden van sommige variabelen naar het terminalvenster af te drukken.
De while
lusvoorwaarde is interessanter dan de hoofdtekst van de lus. We specificeren dat een komma moet worden gebruikt als het interne veldscheidingsteken, met de IFS=","
uitspraak. De IFS is een omgevingsvariabele. De read
commando verwijst naar zijn waarde bij het ontleden van tekstreeksen.
We gebruiken de read
commando’s -r
(backslashes behouden) optie om eventuele backslashes in de gegevens te negeren. Ze worden behandeld als gewone tekens.
De tekst die de read
command parses wordt opgeslagen in een set variabelen genoemd naar de CSV-velden. Ze hadden net zo goed een naam kunnen krijgen field1, field2, ... field7
maar betekenisvolle namen maken het leven gemakkelijker.
De gegevens worden verkregen als de uitvoer van de tail
opdracht. We gebruiken tail
omdat het ons een eenvoudige manier geeft om de kopregel van het CSV-bestand over te slaan. De -n +2
(regelnummer) optie vertelt tail
om te beginnen met lezen bij regel nummer twee.
De <(...)
constructie wordt processubstitutie genoemd. Het zorgt ervoor dat Bash de uitvoer van een proces accepteert alsof het afkomstig is van een bestandsdescriptor. Dit wordt dan doorgestuurd naar de while
lus, met de tekst die de read
opdracht zal ontleden.
Maak het script uitvoerbaar met behulp van de chmod
opdracht. U moet dit elke keer doen als u een script uit dit artikel kopieert. Vervang in elk geval de naam van het juiste script.
chmod +x field.sh
Wanneer we het script uitvoeren, worden de records correct opgesplitst in hun samenstellende velden, waarbij elk veld in een andere variabele wordt opgeslagen.
./field.sh
Elk record wordt afgedrukt als een set velden.
Velden selecteren
Misschien willen of hoeven we niet elk veld op te halen. We kunnen een selectie van velden verkrijgen door de cut
opdracht.
Dit script heet “select.sh.”
#!/bin/bash while IFS="," read -r id jobtitle branch state do echo "Record ID: $id" echo "Job Title: $jobtitle" echo " Branch: $branch" echo " State: $state" echo "" done < <(cut -d "," -f1,4,6,7 sample.csv | tail -n +2)
We hebben de toegevoegd cut
opdracht in de procesvervangingsclausule. We gebruiken de -d
(scheidingsteken) optie om te vertellen cut
komma’s gebruiken “,
” als scheidingsteken. De -f
(veld) optie vertelt cut
we willen velden één, vier, zes en zeven. Die vier velden worden gelezen in vier variabelen, die worden afgedrukt in de hoofdtekst van het while
lus.
Dit is wat we krijgen als we het script uitvoeren.
./select.sh
Door toevoeging van de cut
commando, kunnen we de velden selecteren die we willen en de velden negeren die we niet hebben.
Tot nu toe, zo goed. Maar…
Als de CSV waarmee u te maken heeft ongecompliceerd is zonder komma’s of aanhalingstekens in veldgegevens, zal wat we behandeld hebben waarschijnlijk voldoen aan uw behoeften op het gebied van CSV-parsering. Om de problemen te laten zien die we kunnen tegenkomen, hebben we een kleine steekproef van de gegevens aangepast om er zo uit te zien.
id,firstname,lastname,job-title,email-address,branch,state 1,Rosalyn,Brennan,"Steward, Senior",Rosalyn_Brennan4351@mafthy.com,Minneapolis,Maryland 2,Danny,Redden,"Analyst ""Budget""",Danny_Redden1443@brety.org,Venice,North Carolina 3,Lexi,Roscoe,Pharmacist,,Irlington,Vermont
- Record één heeft een komma in de
job-title
veld, dus het veld moet tussen aanhalingstekens worden geplaatst. - Record twee heeft een woord tussen twee sets aanhalingstekens in de
jobs-title
veld. - Record drie heeft geen gegevens in de
email-address
veld.
Deze gegevens zijn opgeslagen als “sample2.csv.” Pas uw “field.sh” -script aan om “sample2.csv” aan te roepen en sla het op als “field2.sh”.
#! /bin/bash while IFS="," read -r id firstname lastname jobtitle email branch state do echo "Record ID: $id" echo "Firstname: $firstname" echo " Lastname: $lastname" echo "Job Title: $jobtitle" echo "Email add: $email" echo " Branch: $branch" echo " State: $state" echo "" done < <(tail -n +2 sample2.csv)
Wanneer we dit script uitvoeren, kunnen we scheuren zien verschijnen in onze eenvoudige CSV-parsers.
./field2.sh
Het eerste record splitst het functietitelveld op in twee velden, waarbij het tweede deel wordt behandeld als het e-mailadres. Elk veld daarna wordt een plaats naar rechts verschoven. Het laatste veld bevat zowel de branch
en de state
waarden.
Het tweede record behoudt alle aanhalingstekens. Het mag slechts één paar aanhalingstekens hebben rond het woord ‘Budget’.
Het derde record behandelt het ontbrekende veld eigenlijk zoals het hoort. Het e-mailadres ontbreekt, maar verder is alles zoals het hoort.
Contra-intuïtief is het voor een eenvoudig gegevensformaat erg moeilijk om een robuuste algemene CSV-parser te schrijven. Hulpmiddelen zoals awk
zal je dichtbij laten komen, maar er zijn altijd randgevallen en uitzonderingen die er doorheen glippen.
Proberen een onfeilbare CSV-parser te schrijven is waarschijnlijk niet de beste manier om vooruit te komen. Een alternatieve benadering, vooral als u met een of andere deadline werkt, maakt gebruik van twee verschillende strategieën.
Een daarvan is om een speciaal ontworpen tool te gebruiken om uw gegevens te manipuleren en te extraheren. De tweede is om uw gegevens op te schonen en probleemscenario’s zoals ingesloten komma’s en aanhalingstekens te vervangen. Uw eenvoudige Bash-parsers kunnen dan omgaan met de Bash-vriendelijke CSV.
De csvkit-toolkit
De CSV-toolkit csvkit
is een verzameling hulpprogramma’s die speciaal zijn gemaakt om te helpen bij het werken met CSV-bestanden. U moet het op uw computer installeren.
Gebruik deze opdracht om het op Ubuntu te installeren:
sudo apt install csvkit
Om het op Fedora te installeren, moet je typen:
sudo dnf install python3-csvkit
Op Manjaro is het commando:
sudo pacman -S csvkit
Als we de naam van een CSV-bestand doorgeven, wordt de csvlook
hulpprogramma geeft een tabel weer met de inhoud van elk veld. De veldinhoud wordt weergegeven om te laten zien wat de veldinhoud vertegenwoordigt, niet zoals ze zijn opgeslagen in het CSV-bestand.
Laten we proberen csvlook
met ons problematische bestand “sample2.csv”.
csvlook sample2.csv
Alle velden worden correct weergegeven. Dit bewijst dat het probleem niet de CSV is. Het probleem is dat onze scripts te simplistisch zijn om de CSV correct te interpreteren.
Gebruik de om specifieke kolommen te selecteren csvcut
opdracht. De -c
(kolom) optie kan worden gebruikt met veldnamen of kolomnummers, of een combinatie van beide.
Stel dat we de voor- en achternaam, functietitels en e-mailadressen uit elke record moeten extraheren, maar we willen de naamvolgorde hebben als ‘achternaam, voornaam’. Het enige wat we hoeven te doen is de veldnamen of nummers in de gewenste volgorde te zetten.
Deze drie commando’s zijn allemaal equivalent.
csvcut -c lastname,firstname,job-title,email-address sample2.csv
csvcut -c lastname,firstname,4,5 sample2.csv
csvcut -c 3,2,4,5 sample2.csv
We kunnen de toevoegen csvsort
opdracht om de uitvoer op een veld te sorteren. We gebruiken de -c
(kolom) optie om de kolom op te geven waarop moet worden gesorteerd, en de -r
(omgekeerde) optie om in aflopende volgorde te sorteren.
csvcut -c 3,2,4,5 sample2.csv | csvsort -c 1 -r
Om de uitvoer mooier te maken, kunnen we deze doorvoeren csvlook
.
csvcut -c 3,2,4,5 sample2.csv | csvsort -c 1 -r | csvlook
Een leuke bijkomstigheid is dat, ook al zijn de records gesorteerd, de kopregel met de veldnamen als eerste regel behouden blijft. Zodra we tevreden zijn dat we de gegevens hebben zoals we het willen, kunnen we de csvlook
vanuit de opdrachtketen en maak een nieuw CSV-bestand door de uitvoer om te leiden naar een bestand.
We hebben meer gegevens toegevoegd aan het “sample2.file”, het verwijderd csvsort
opdracht en maakte een nieuw bestand met de naam “sample3.csv.”
csvcut -c 3,2,4,5 sample2.csv > sample3.csv
Een veilige manier om CSV-gegevens op te schonen
Als u een CSV-bestand opent in LibreOffice Calc, wordt elk veld in een cel geplaatst. U kunt de zoek- en vervangfunctie gebruiken om naar komma’s te zoeken. U kunt ze vervangen door ‘niets’ zodat ze verdwijnen, of door een teken dat geen invloed heeft op de CSV-parsering, zoals een puntkomma ‘;
” bijvoorbeeld.
U ziet de aanhalingstekens rond geciteerde velden niet. De enige aanhalingstekens die u ziet, zijn de ingesloten aanhalingstekens binnenkant veld gegevens. Deze worden weergegeven als enkele aanhalingstekens. Deze zoeken en vervangen door een enkele apostrof “'
” vervangt de dubbele aanhalingstekens in het CSV-bestand.
Zoeken en vervangen in een toepassing zoals LibreOffice Calc betekent dat u niet per ongeluk een van de komma’s voor het scheiden van velden kunt verwijderen, noch de aanhalingstekens rond velden tussen aanhalingstekens kunt verwijderen. Je verandert alleen de gegevens waarden van velden.
We hebben alle komma’s in velden met puntkomma’s en alle ingesloten aanhalingstekens met apostrofs gewijzigd en onze wijzigingen opgeslagen.
Vervolgens hebben we een script gemaakt met de naam “field3.sh” om “sample3.csv” te ontleden.
#! /bin/bash while IFS="," read -r lastname firstname jobtitle email do echo " Lastname: $lastname" echo "Firstname: $firstname" echo "Job Title: $jobtitle" echo "Email add: $email" echo "" done < <(tail -n +2 sample3.csv)
Laten we eens kijken wat we krijgen als we het uitvoeren.
./field3.sh
Onze eenvoudige parser kan nu onze eerder problematische records aan.
Je zult veel CSV zien
CSV komt misschien wel het dichtst in de buurt van een gemeenschappelijke taal voor applicatiegegevens. De meeste toepassingen die een bepaalde vorm van gegevens verwerken, ondersteunen het importeren en exporteren van CSV. Als u weet hoe u op een realistische en praktische manier met CSV om moet gaan, komt u goed van pas.