Puncte:-1

Cum se extrage un șir dintr-un fișier json și se pune într-o variabilă (Linux)

drapel us

Am următoarele într-unul din fișierul meu json file1.json :-

{
  „$quer”: {
    „args”: [{
      „args”: [
        „selectați\n db1.table1 ca tab1,\n db1.table2 ca tab2,\n db1.table3 ca tab3\n din db1.table4 ca tab4”
      ],
      "fn": "din-sql",
      "ns": "op"
    }],
    "fn": "operatori",
    "ns": "op"
  }
}

Vreau să extrag șirul db1.table4 din acest fișier json și stocați într-o variabilă.

Nu știu multe despre sed și awk. Poate cineva să ajute aici?

terdon avatar
drapel cn
Cum putem ști ce să extragem? Ar trebui să fie întotdeauna al doilea cuvânt din primul element din matricea `args`? Ar trebui să fie orice se află după `select\n`? Cum putem identifica partea din fișier pe care doriți să o extrageți?
Puncte:2
drapel ru

Aruncă o privire la jq procesorul JSON din linia de comandă, instalați de exemplu cu:

sudo apt install jq

Șirul pe care îl doriți nu este o valoare JSON, face parte dintr-o valoare JSON. Așa că vă sugerez să utilizați jq pentru a obține șirul pe care trebuie să îl manipulați într-o variabilă, de exemplu:

my_var=$(jq -r .[$quer].args[0].args[0] file1.json)

Aceasta vă obține o variabilă care conține instrucțiunea SELECT:

selectați db1.table1 ca tab1, db1.table2 ca tab2, db1.table3 ca tab3 din db1.table4 ca tab4

Apoi va trebui să utilizați alte instrumente precum sed, awk, cut etc. pentru a obține subșirul dorit de la acea variabilă. Pentru cazul dvs. specific, acest lucru ar funcționa, dar desigur s-ar putea să nu funcționeze pentru o instrucțiune SELECT diferită. Tăierea prin delimitator de spațiu și returnarea celei de-a 12-a valori:

tabela_mea=$(echo $var_mea | cut -d' ' -f12)
Aviator avatar
drapel us
este deja acolo, dar întrebarea mea nu este legată de json, este de a folosi comanda Unix.
terdon avatar
drapel cn
@Aviator `jq` _este_ o comandă, la fel ca oricare alta. Este instrumentul potrivit de utilizat atunci când analizați fișierele json.
codlord avatar
drapel ru
Exemple adăugate mai sus.
terdon avatar
drapel cn
Mulțumiri! asta e mult mai clar :)
Puncte:2
drapel us
  1. Să presupunem că șirul pe care doriți să îl extrageți se află în aceeași poziție în fiecare fișier pe care îl puteți utiliza cap, coadă și a tăia comenzi folosind conducte.

  2. De exemplu:

    $ head -6 file.json | coada -1 | tăiat -b 121-129
    db1.tabel
    
  3. Și iată un exemplu de script care setează rezultatul într-o variabilă:

    #!/bin/bash
    v1=$(head -6 file.json | coada -1 | cut -b 121-130)
    ecou „$v1”
    

Ieșirea scriptului va fi db1.table4 care este valoarea V1 variabilă.

Puteți citi mai multe despre aceste comenzi aici:

Desigur, puteți folosi acele comenzi pentru a extrage orice alt șir dintr-un fișier.

Aviator avatar
drapel us
Mulțumesc mult. m-a ajutat.
Puncte:1
drapel cn

În general, ar trebui să evitați utilizarea instrumentelor generice de analiză a textului pentru date structurate. Deoarece aveți un fișier json, este mai sigur și mai simplu să utilizați un parser json dedicat. În cazul dvs., ați dori să extrageți valoarea primului element al matricei argumente care este el însuși primul element al matricei de nivel superior argumente, copilul hashului de nivel superior $quer:

$ jq '."$quer"."args"[0]["args"]' fișier.json
[
  „selectați\n db1.table1 ca tab1,\n db1.table2 ca tab2,\n db1.table3 ca tab3\n din db1.table4 ca tab4”
]

De aici, nu mai ai date structurate și trebuie să apelezi la metode mai crude. Nu știu cum vrei să-ți identifici șirul țintă, nu ai explicat asta. Deci, în funcție de ceea ce doriți de fapt, puteți face:

  1. Omite rândurile începând cu [ sau ] și apoi tipăriți al doilea cuvânt din rândurile rămase:

    $ jq '."$quer"."args"[0]["args"]' fișier.json | awk '/^[^][]/{printează $2}'
    db1.table1
    
  2. Tipăriți al doilea cuvânt din a doua linie

    $ jq '."$quer"."args"[0]["args"]' fișier.json | awk 'NR==2{printează $2}'
    db1.table1
    
  3. Tipăriți cea mai lungă porțiune de non-spațiu alb după șir „selectați\n:

    $ jq '."$quer"."args"[0]["args"]' fișier.json | grep -oP '"select\n\s*\K\S*'
    db1.table1
    

Dacă explicați exact cum ar trebui să știm ce șir să extragem, aș putea să vă dau un răspuns mai precis.


De dragul finalizării, în dvs specific exemplu, și subliniez că acest lucru nu va fi portabil și este aproape sigur că va eșua dacă datele dvs. de intrare se schimbă în vreun fel, puteți utiliza instrumente simple de text direct:

$ grep -oP „select\n\s*\K\S*” fișier.json 
db1.table1

$ awk '$1=="\"select\n"{printează $2}' file.json 
db1.table1

$ sed -nE 's/.*"select\n\s*(\S+).*/\1/p' file.json 
db1.table1
drapel hr
Ați putea, eventual, să faceți unele dintre awk-like slicing'n'dicing în jq, de exemplu `jq -r '."$quer".args[0].args[] | split("\n")[-1] | split(" ")[-3]' fișier.json` sau poate ceva bazat pe regex, cum ar fi `jq -r '."$quer".args[0].args[] | capture("de la (?[^ ]+)") | .a'`
terdon avatar
drapel cn
@steeldriver da, dar m-am gândit că, din moment ce nu știu ce vrea de fapt să extragă OP, aș putea la fel de bine să ofer câteva alegeri simple.
drapel hr
într-adevăr... nu este clar

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.