Forstå JSON-data med jq i Linux-kommandolinjen
JSON, eller JavaScript Object Notation, er et svært utbredt format for dataoverføring på internett. Det er nærmest overalt, og du vil garantert støte på det. Her skal vi utforske hvordan du kan håndtere JSON-data direkte fra Linux-kommandolinjen ved hjelp av verktøyet jq
.
Hva er JSON og jq?
JSON er en tekstbasert metode for å representere strukturerte data. Det kjennetegnes ved at dataene er selvforklarende, med nøkkel-verdi par som beskriver innholdet. En JSON-fil inneholder ikke kommentarer, og all informasjon presenteres i form av tekststrenger.
Et objekt i JSON er en samling av nøkkel-verdi par, omsluttet av krøllparenteser ({}
). En matrise er en ordnet liste av verdier, avgrenset av hakeparenteser ([]
). Disse enkle byggeklossene kan kombineres på komplekse måter, med objekter inne i objekter eller matriser, og matriser inne i objekter eller matriser.
Selv om JSON-strukturer kan bli kompliserte, er det viktig å holde dem oversiktlige. For kompliserte datastrukturer kan det være fornuftig å revurdere designet. I situasjoner der du ikke har kontroll over JSON-dataenes utforming, må du likevel forholde deg til det.
De fleste programmeringsspråk har verktøy for å tolke JSON-data. Bash-skallet derimot mangler dette, noe som gjør det vanskelig å jobbe direkte med JSON i kommandolinjen. Her kommer jq
inn i bildet. Dette er et kraftig kommandolinjeverktøy som gjør det enkelt å behandle og analysere JSON-data, enten det er pent formatert eller en uoversiktlig suppe.
Installere jq
For å ta i bruk jq
, må det først installeres. Følgende kommandoer kan brukes for å installere jq
på forskjellige Linux-distribusjoner:
Ubuntu: |
sudo apt-get install jq |
Fedora: |
sudo dnf install jq |
Manjaro: |
sudo pacman -Sy jq |
Gjør JSON lesbar
JSON er ikke avhengig av mellomrom og formatering, og overføres ofte som en lang sammenhengende streng. Dette sparer plass, men gjør det vanskelig å lese for mennesker. La oss se hvordan jq
kan hjelpe oss med dette.
Vi skal hente et JSON-objekt fra NASA, som inneholder data om posisjonen til den internasjonale romstasjonen. Kommandoen curl
kan brukes for å laste ned denne dataen.
For å unngå unødvendig informasjon fra curl
, bruker vi -s
(stille) parameteren:
curl -s http://api.open-notify.org/iss-now.json
Dette gir oss en lang, uoversiktlig streng. Ved å bruke jq
og punktumet (.
) som filter, kan vi enkelt formatere JSON-utdataene:
curl -s http://api.open-notify.org/iss-now.json | jq .
Nå er JSON-dataene mye enklere å lese. Vi ser nøkkel-verdi parene, som inkluderer en melding, tidsstempel og et objekt kalt iss_position
, som igjen inneholder lengdegrad og breddegrad.
For å lagre de formaterte utdataene i en fil, kan vi omdirigere utdataene fra jq
:
curl -s http://api.open-notify.org/iss-now.json | jq . > iss.json
cat iss.json
Dette gir oss en formateret JSON-fil på disken vår.
Tilgang til dataverdier
Når vi har JSON-data, kan vi bruke jq
for å trekke ut spesifikke verdier. Den enkleste metoden er å angi nøkkelnavnet etter et punktum (.
). Vi kan bruke filen iss.json
som vi lagret i forrige avsnitt:
jq .message iss.json
Dette skriver ut verdien assosiert med nøkkelen message
.
jq .timestamp iss.json
Dette henter ut tidsstemplet. Hvis en nøkkel inneholder mellomrom eller andre tegn, må nøkkelnavnet settes i anførselstegn. For å få tilgang til data i et nestet objekt, bruker vi JSON-punktnotasjon, som vist nedenfor:
jq .iss_position.latitude iss.json
Dette henter breddegraden. For å hente flere verdier samtidig, separerer vi dem med komma og setter hele uttrykket i anførselstegn:
jq ".iss_position.latitude, .timestamp" iss.json
Jobbe med matriser
La oss utforske hvordan vi kan jobbe med matriser i JSON. Vi skal hente en liste over alle astronautene som befinner seg i verdensrommet fra NASA:
curl -s http://api.open-notify.org/astros.json
For å lagre dataene i filen astro.json
, gjør vi følgende:
curl -s http://api.open-notify.org/astros.json | jq . > astro.json
For å inspisere filen, kan vi bruke less
:
less astro.json
Denne JSON-strukturen inneholder en matrise kalt people
, der hvert objekt har et navn og et fartøy. Vi bruker punktnotasjonen for å hente ut informasjonen, inkludert hakeparenteser []
for å spesifisere matrisen:
jq ".people[].name" astro.json
Dette henter ut alle navnene fra objektene i people
matrisen. For å hente navnet fra et bestemt objekt, bruker vi indeksen i hakeparentesene. Husk at matriser bruker nullbasert indeksering. For å hente det første objektet bruker vi [0]
, det andre objektet bruker [1]
. For å hente det siste elementet i matrisen, bruker vi [-1]
, det nest siste bruker vi [-2]
, og så videre.
La oss demonstrere dette med noen eksempler:
jq ".people[1].name" astro.json
jq ".people[3].name" astro.json
jq ".people[-1].name" astro.json
jq ".people[-2].name" astro.json
Vi kan også hente ut en del av matrisen, også kjent som et snitt. For å hente objektene fra indeks 2 til 4 (der objektet på indeks 4 ikke inkluderes), bruker vi [2:4]
:
jq ".people[2:4]" astro.json
Bruke rør med filtre
Akkurat som i vanlig Linux-bruk, kan vi også bruke rør (|
) for å kombinere flere filtre i jq
. La oss bruke det til å hente navnene på astronautene:
jq ".people[] | .name" astro.json
Først henter vi people
-matrisen, så bruker vi .name
til å trekke ut navnet fra hvert objekt.
Opprette matriser og endre resultater
Vi kan også bruke jq
til å lage nye JSON-objekter, som matriser. La oss lage en matrise med breddegrad, lengdegrad og tidsstempel fra iss.json
:
jq "[.iss-position.latitude, .iss_position.longitude, .timestamp]" iss.json
Vi ser at utdataene nå er en matrise med de tre verdiene.
Vi kan også manipulere numeriske verdier, for eksempel ved å trekke fra en konstant fra tidsstemplet:
jq ".timestamp" iss.json
jq ".timestamp - 1570000000" iss.json
La oss se hvordan iss.json
-filen ser ut på nytt:
jq . iss.json
For å fjerne et nøkkel-verdi par, kan vi bruke del()
-funksjonen. La oss fjerne message
fra iss.json
:
jq "del(.message)" iss.json
Merk at dette ikke endrer filen iss.json
, bare utdataene fra kommandoen. For å lagre endringen i en fil, må du omdirigere utdataene til en ny fil.
Mer kompliserte JSON-objekter
La oss se på et større og mer komplekst JSON-objekt som inneholder data om meteornedslag. Først laster vi ned og lagrer dataene i filen strikes.json
:
curl -s https://data.nasa.gov/resource/y77d-th95.json | jq . > strikes.json
La oss se hvordan filen ser ut:
less strikes.json
Filen starter med en hakeparentes ([
), så den er en matrise. Hvert objekt i matrisen inneholder nøkkel-verdi par, inkludert et nestet geolocation
-objekt, som har et koordinat array. La oss hente ut navnene på meteornedslagene fra indeks 995 og ut matrisens slutt:
jq ".[995:] | .[] | .name" strikes.json
Kommandoen gjør følgende: Først henter den objekter fra indeks 995 til slutten ([995:]
). Deretter behandler den hvert objekt i matrisen (.[]
). Til slutt henter den navnet (.name
). For å hente de ti siste objektene, kan vi bruke [-10:]
:
jq ".[-10:] | .[] | .name" strikes.json
For å hente et enkelt objekt med indeks 650:
jq ".[650].name" strikes.json
Vi kan også dele opp tekststrenger, la oss ta de første fire tegnene av objektet i indeks 234:
jq ".[234].name[0:4]" strikes.json
For å vise et helt objekt med indeks 234:
jq ".[234]" strikes.json
Om vi kun vil se verdiene, uten nøklene:
jq ".[234][]" strikes.json
<img loading=»lazy» decoding=»async» src=»https://tipsbilk.net/wp-content/uploads/2022/02/1645294954_43_Hvordan-analysere-JSON-filer-pa-Linux-kommandolinjen-med-jq.png» alt=»Kommandoen jq .[234][] strikes.json i et terminalvind