Mester JSON på Linux-kommandolinjen med jq!


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