Analyser en streng i bash-skript

Jeg gjennomgikk andre svar, men kunne ikke få en skikkelig forklaring på hvordan jeg gjør dette.

I ha en strengvariabel kalt id slik at id="{"name":"john"}". Hvordan kan jeg få to variabler ut av denne strengen som-

key="name" value="john" 

En detaljert forklaring vil bli satt pris på da jeg vil forstå strenganalyse i bash.

Så langt har jeg fjernet tannreguleringene {} fra strengen-

id="$( echo "${id}" | tr -d {} )" 

Jeg kan ikke inkludere " der inne som det kaster en feil. Ser også etter noe som id.split(":") til slutt for å få en matrise.

Kommentarer

  • Kan vi advare deg om denne taktikken / sporet før det ' er for sent? Det ser ut til at du har json eller noen andre strukturerte data der. Kanskje et dedikert verktøy ville være en tryggere måte å komme deg dit du går?
  • Jeg så at jq brukes av andre, men er det ingen måte jeg kan analysere dette uten en tredjepart verktøy?
  • Kommer du med disse dataene fra en fil? Kan det være mer enn ett par nøkkel / verdier? Hvordan ville et dobbelt sitat se ut som en del av verdien?
  • @kev: Teknisk sett awk, sed , og grep er også tredjepartsverktøy. Hvis du bruker json data, er det absolutt ingen grunn til ikke å ha de riktige verktøyene for å jobbe med dem.
  • Disse dataene er resultatet av en kommando som jeg utført i skriptet mitt. Det vil alltid være i dette formatet – en nøkkel og en verdi.

Svar

Bruk jq:

id="{"name":"john"}" key=$(jq -r keys[] <<<"$id") value=$(jq -r .[] <<<"$id") 

-r: Med dette alternativet, hvis filteret «s resultatet er en streng, så vil den bli skrevet direkte til standardutdata i stedet for å bli formatert som en JSON-streng med anførselstegn.

keys: De innebygde funksjonstastene når gitt et objekt, returnerer nøklene i en matrise.


Bruk json:

id="{"name":"john"}" key=$(json -ak <<<"$id") value=$(json -a "$key" <<<"$id") 

-a behandler inngang som en matrise

-k returnerer nøkkelverdier

Kommentarer

  • takk for forklaringen. Fungerer bra. Jeg regner med at ' ingen måte å analysere en streng uten jq i bash-skript.
  • @kev: Det er mange måter å analysere strenger på, men det ' er slags urettferdig for å kalle dette en streng og ikke json-data.
  • @kev JSON-data kan kodes. For å analysere det, vil du potensielt måtte dekode det. Dessuten bryr JSON seg ikke om mellomrom (nye linjer osv.) Mellom nøkler og verdier, så du må ta hensyn til det. Dette har allerede blitt gjort for deg av forfatterne av den underliggende JSON-parseren i jq.

Svar

Du ba bokstavelig talt om å understand string parsing in bash så jeg skriver et svar med tanke på det, selv om det er feil løsning for problemet ditt . Du kan bruke bash selv til å gjøre det du vil, hvis du har virkelig ren data uten spesialtegn, der spesiell er definert som alt utenfor [A-Za-z0-9 ]:

$name":"john"}" $ # remove everything through the first "{" $ echo $id "name":"john"} $ # remove everything starting with the last "}" $ echo $id "name":"john" $ name="${id%:*}" # take everything before the ":" $ name="${name//\"/}" # remove quotes $ echo $name name $ value="${id#*:}" # take everything after the ":" $ value="${value//\"/}" # remove quotes $ echo $value john 

Dette er alt beskrevet i «Parameter Expansion» i bash manual . For eksempel ${parameter#word} som vil Remove matching prefix pattern fjerner teksten word fra begynnelsen av $parameter. Tilsvarende fjerner % suffikset. // erstatter alle forekomster av en streng med hva som kommer etter den (i ${foo//\"/} eksempelet ovenfor, anførselstegn (som må unnslippes, så vises som \") erstattes med den tomme strengen). Du må utføre hver erstatning alene, men du kan ikke fjerne begynnelsen og slutten av strengen med en kommando.

Du har også sannsynligvis lagt merke til at du trenger å unnslippe spesialtegn, som }, { og ". Så lenge du husker å få det riktig, kan du skrive kode ganske enkelt, men, så enkelt som det er, trender det mot å være skrivekode. Når du kommer tilbake til dette kode om et år eller to for å bruke den på nytt, vil du se på noe som #*\{} og tenke for deg selv, WTF betyr det til og med? og så er det bare å kopiere det blindt inn i et nytt prosjekt, så vil koden din bryte på en subtil måte fordi den møter spesialtegn som du ikke forventet.

Eksemplene ovenfor vil brytes hvis parene med navn og verdi har spesialtegn, som klammeparenteser eller rømte anførselstegn eller kolon eller sannsynligvis andre tegn. Så dette vil fungere bra for noe skittent og skittent skrap eller 80% brukstilfelle, men du bør egentlig ikke bruke det i produksjonen eller når som helst du trenger for å sørge for at det alltid fungerer med alle input.

Selv uten echo utsagnene der inne for å vise deg hva som skjer, kan du se at denne koden allerede er lenger enn eksemplene i det andre svaret som viser hvordan du gjør det ordentlig. Så ved ikke å bruke et tredjepartsverktøy gir du deg mer kode å skrive, noe som vil ta deg lengre tid å både skrive og feilsøke, og du vil også ende opp med en løsning som er mindre fleksibel og som vil pause når det møter noe uventet.

Kommentarer

  • dette var ganske informativt – kan ' t forstå hvorfor folk ville nedstemme

Svar

Alternativt kan du bruke en sti-basert unix verktøy jtc :

id="{"name":"john"}" bash $ key=$(jtc -w"[0]<>k" <<<"$id") bash $ echo $key "name" bash $ value=$(jtc -w"[0]" <<<"$id") bash $ echo $value "john" bash $ 

PS> Opplysning: Jeg er skaperen av jtc – shell cli-verktøyet for JSON-operasjoner

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *