Parseer een string in bash-script

Ik heb andere antwoorden bekeken, maar kreeg geen goede uitleg over hoe dit te doen.

I heb een stringvariabele genaamd id zodanig dat id="{"name":"john"}". Hoe kan ik 2 variabelen uit deze string krijgen zoals-

key="name" value="john" 

Een gedetailleerde uitleg zou op prijs worden gesteld, aangezien ik string-parsing in bash wil begrijpen.

Tot dusver heb ik “de accolades verwijderd {} van de string-

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

Ik kan” " daarin niet opnemen als het genereert een fout. Ook op zoek naar iets als id.split(":") om een array te krijgen.

Reacties

  • Kunnen we je waarschuwen voor deze tactiek / track voordat deze ‘ te laat is? Het lijkt erop dat je daar json of andere gestructureerde gegevens hebt; misschien is een speciale tool een veiligere manier om u te brengen waar u re going?
  • Ik zag dat jq door anderen wordt gebruikt, maar kan ik dit op geen enkele manier ontleden zonder een derde partij tool?
  • Brengt u deze gegevens uit een bestand? Kunnen er meer dan één paar sleutel / waarden zijn? Hoe ziet een dubbel aanhalingsteken eruit als onderdeel van de waarde?
  • @kev: Technisch gezien awk, sed , en grep zijn ook tools van derden. Als u json -gegevens gebruikt, is er absoluut geen reden om niet over de juiste tools te beschikken om ermee te werken.
  • Deze gegevens zijn het resultaat van een opdracht die ik uitgevoerd in mijn script. Het zal altijd in dit formaat zijn: 1 sleutel en 1 waarde.

Antwoord

Met jq:

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

-r: met deze optie, als het filter “s resultaat is een tekenreeks, dan wordt het direct naar de standaarduitvoer geschreven in plaats van te worden opgemaakt als een JSON-tekenreeks met aanhalingstekens.

keys: de ingebouwde functietoetsen, wanneer gegeven een object, retourneert zijn sleutels in een array.


Met json:

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

-a verwerkt invoer als een array

-k retourneert sleutelwaarden

Opmerkingen

  • bedankt voor de uitleg. Werkt prima. Ik denk dat er ‘ s geen manier is om een string te ontleden zonder jq in bash-scripts.
  • @kev: Er zijn tal van manieren om strings te parseren, maar het is ‘ een beetje oneerlijk om dit een string te noemen en geen json-gegevens.
  • @kev JSON-gegevens kunnen worden gecodeerd. Om het te ontleden, zou je het mogelijk moeten decoderen. Ook geeft JSON niets om witruimte (nieuwe regels etc.) tussen sleutels en waarden, dus daar moet je rekening mee houden. Dit is al voor u gedaan door de auteurs van de onderliggende JSON-parser in jq.

Antwoord

Je hebt letterlijk gevraagd om understand string parsing in bash, dus ik zal een antwoord schrijven met dat in gedachten, ook al is het de verkeerde oplossing voor uw probleem . Je kunt bash zelf gebruiken om te doen wat je wilt, if je hebt echt schoon gegevens zonder speciale tekens, waarbij speciaal wordt gedefinieerd als alles buiten [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 

Dit wordt allemaal beschreven in “Parameter Expansion” in de bash-handleiding . Bijvoorbeeld: ${parameter#word} die Remove matching prefix pattern zal de tekst word vanaf het begin van $parameter. Evenzo verwijdert % het achtervoegsel. // vervangt alle keren dat een string voorkomt door wat erna komt (in het ${foo//\"/} voorbeeld hierboven, aanhalingstekens (die moeten worden ontsnapt, dus verschijnen als \") worden vervangen door de lege string). Je moet echter elke vervanging zelf uitvoeren: je kunt “het begin en einde van de string niet verwijderen met één commando.

Je hebt waarschijnlijk ook gemerkt dat je moeten ontsnappen aan speciale tekens, zoals }, { en ". Zolang je eraan denkt om dat goed te doen, kun je vrij gemakkelijk schrijven code op deze manier vrij gemakkelijk schrijven , maar hoe simpel het ook is, het neigt ernaar om alleen-schrijven code te zijn. code in een jaar of twee om het opnieuw te gebruiken, “kijk je naar iets als #*\{} en denk bij jezelf: WTF betekent dat zelfs? en kopieer het dan blindelings naar een nieuw project en dan zal je code op een subtiele manier breken omdat het speciale karakters tegenkomt die je niet had verwacht.

De bovenstaande voorbeelden worden afgebroken als uw naam-waardeparen speciale tekens bevatten, zoals accolades of ontsnapte aanhalingstekens of dubbele punten of waarschijnlijk andere tekens. Dus dit zal prima werken voor wat snel en vies schrapen of de 80% use case, maar je zou het echt niet moeten gebruiken in productie of wanneer je maar wilt om ervoor te zorgen dat het altijd werkt met welke input dan ook.

Zelfs zonder de echo instructies erin om je te laten zien wat er gebeurt, kun je zien dat deze code al langer is dan de voorbeelden in het andere antwoord die laten zien hoe je het moet doen naar behoren. Dus door geen tool van derden te gebruiken, “geef je jezelf meer code om te schrijven, waardoor je meer tijd nodig hebt om zowel te schrijven als te debuggen, en je eindigt ook met een oplossing die minder flexibel is en die zal breken wanneer het iets onverwachts tegenkomt.

Reacties

  • dit was vrij informatief – kan ‘ t begrijpen waarom mensen zouden downstemmen

Answer

Als alternatief zou je een op wandelpad gebaseerde unix kunnen gebruiken hulpprogramma 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> Openbaarmaking: ik “ben de maker van de jtc – shell cli-tool voor JSON-bewerkingen

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *