Analysera en sträng i bash-skript

Jag granskade andra svar men kunde inte få en ordentlig förklaring till hur man gör det.

I har en strängvariabel som heter id så att id="{"name":"john"}". Hur kan jag få 2 variabler ur denna sträng som-

key="name" value="john" 

En detaljerad förklaring skulle uppskattas eftersom jag vill förstå strängparsning i bash.

Hittills har jag tagit bort hängslen {} från strängen-

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

Jag kan inte inkludera " där inne som det kastar ett fel. Letar också efter något som id.split(":") i slutändan för att få en matris.

Kommentarer

  • Kan vi varna dig för denna taktik / spår innan den ' är för sent? Det verkar som om du har json eller någon annan strukturerad data där, kanske skulle ett dedikerat verktyg vara ett säkrare sätt att ta dig dit du pågår?
  • Jag såg att jq används av andra, men kan jag inte analysera detta utan en tredje part verktyg?
  • Tar du in dessa data från en fil? Kan det finnas mer än ett par nyckel / värden? Hur skulle ett dubbelt citat se ut som en del av värdet?
  • @kev: Tekniskt awk, sed , och grep är också verktyg från tredje part. Om du använder json data finns det absolut ingen anledning att inte ha rätt verktyg för att arbeta med dem.
  • Dessa data är resultatet av ett kommando som jag körs i mitt skript. Det kommer alltid att vara i det här formatet – en nyckel och ett värde.

Svar

Använd jq:

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

-r: Med detta alternativ, om filtret ”s resultatet är en sträng, då kommer den att skrivas direkt till standardutdata istället för att formateras som en JSON-sträng med citat.

keys: De inbyggda funktionstangenterna, när ges ett objekt, returnerar dess nycklar i en matris.


Med json:

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

-a bearbetar inmatning som en array

-k returnerar nyckelvärden

Kommentarer

  • tack för förklaringen. Fungerar bra. Jag tror att ' inte kan analysera en sträng utan jq i bash-skript.
  • @kev: Det finns många sätt att analysera strängar men det ' är typ av orättvist för att kalla detta en sträng och inte json-data.
  • @kev JSON-data kan kodas. För att analysera det skulle du eventuellt behöva avkoda det. Dessutom bryr sig JSON inte om mellanslag (nylinjer etc.) mellan nycklar och värden, så du måste ta hänsyn till det. Detta har redan gjorts åt dig av författarna till den underliggande JSON-analysatorn i jq.

Svar

Du bad bokstavligen understand string parsing in bash så jag skriver ett svar med det i åtanke, även om det är fel lösning på ditt problem . Du kan använda bash själv för att göra vad du vill, om har du riktigt ren data utan specialtecken, där special definieras som något utanför [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 

Allt detta beskrivs i ”Parameter Expansion” i bash manual . Till exempel ${parameter#word} som kommer att Remove matching prefix pattern tar bort texten word från början av $parameter. På samma sätt tar % bort suffixet. // ersätter alla förekomster av en sträng med vad som kommer efter den (i ${foo//\"/} exempel ovan, citat (som måste undvikas, så visas som \") ersätts med den tomma strängen). Du måste dock utföra varje byte av sig själv: du kan inte ta bort början och slutet av strängen med ett kommando.

Du har antagligen också märkt att du måste undkomma specialtecken, som }, { och ". Så länge du kommer ihåg att få rätt, kan du skriva kod så här ganska enkelt, men så enkelt som det är, trender det mot att vara enbart skrivkod. När du kommer tillbaka till detta kod om ett år eller två för att återanvända den, kommer du att titta på något som #*\{} och tänka för dig själv, WTF betyder det ens? och sedan bara kopiera den blindt till ett nytt projekt och sedan kommer din kod att brytas på ett subtilt sätt eftersom den stöter på specialtecken som du inte förväntade dig.

Exemplen ovan kommer att brytas om dina namn-värde-par har specialtecken i sig, som parenteser eller undantagna citat eller kolon eller förmodligen andra tecken. Så det kommer att fungera bra för snabb och smutsig skrapning eller 80% användningsfall, men du borde verkligen inte använda det i produktionen eller när som helst du behöver för att se till att det alltid fungerar med någon ingång.

Även utan echo uttalanden där inne för att visa vad som händer kan du se att den här koden redan är längre än exemplen i det andra svaret som visar hur du gör det ordentligt. Genom att inte använda ett tredjepartsverktyg ger du dig själv mer kod att skriva, vilket tar dig längre tid att både skriva och felsöka, och du slutar också med en lösning som är mindre flexibel och som kommer att paus när det stöter på något oväntat.

Kommentarer

  • det var ganska informativt – kan ' t förstå varför folk skulle rösta ned

Svar

Alternativt kan du använda en gångbaserad unix verktyg 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> Upplysning: Jag är skaparen av jtc – shell cli-verktyget för JSON-operationer

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *