Διαδρομές
/
jq
jq
/
Ύλη
/
Τα βασικά
Τα

Τα βασικά σε jq

1 άσκηση

Σχετικά με την έννοια Τα βασικά

Το jq λειτουργεί περνώντας τα εισερχόμενα δεδομένα JSON μέσα από μία ενιαία έκφραση (γραμμένη ως σωλήνωση φίλτρων) για να πετύχεις τα επιθυμητά μετασχηματισμένα δεδομένα.

Μια γρήγορη εισαγωγή στις επιλογές γραμμής εντολών του jq

Η γλώσσα jq υλοποιείται από το πρόγραμμα jq. Αυτό το πρόγραμμα παρέχει αρκετές βολικές επιλογές γραμμής εντολών για να ελέγχεις πώς καταναλώνεται η είσοδος και πώς παρουσιάζεται η έξοδος.

Στα παρακάτω παραδείγματα θα συναντήσεις:

  • -n ή --null-input

    Κανονικά στο πρόγραμμα jq δίνεται ένα αρχείο για ανάγνωση, ή στέλνεις δεδομένα στην είσοδό του. Η επιλογή --null-input σου επιτρέπει να παράγεις δεδομένα JSON χωρίς καμία είσοδο.

  • -c ή --compact-output

    Το jq μορφοποιεί όμορφα την έξοδό του από προεπιλογή. Είναι εξαιρετικά χρήσιμο για τους ανθρώπους να βλέπουν τα δεδομένα όταν είναι όμορφα μορφοποιημένα. Ωστόσο, αυτό δεν είναι απαραίτητο για τις μηχανές: η επιλογή --compact-output αφαιρεί τα κενά μορφοποίησης για να ελαχιστοποιήσει το μέγεθος του JSON που προκύπτει.

  • -f filename ή --from-file filename

    Διάβασε το πρόγραμμα jq από το filename αντί να το δίνεις στη γραμμή εντολών. Τόσο το sed όσο και το awk χρησιμοποιούν την επιλογή -f για τον ίδιο σκοπό. Θα το δεις αυτό να χρησιμοποιείται στα σενάρια δοκιμών για τις ασκήσεις πρακτικής.

Δες το εγχειρίδιο για λεπτομέρειες σχετικά με όλες τις επιλογές.

Φίλτρα και σωλήνες

Τα φίλτρα είναι επίσης γνωστά ως εκφράσεις.

Ένα φίλτρο δέχεται μια είσοδο και παράγει μια έξοδο. Όπως ακριβώς δουλεύεις σε ένα κέλυφος unix, μπορείς να ενώσεις φίλτρα με έναν σωλήνα | για να συνδέσεις την έξοδο του ενός φίλτρου με την είσοδο του άλλου.

Το φίλτρο ταυτότητας: .

Αυτό είναι το πιο απλό φίλτρο. Περνά απλώς την είσοδό του στην έξοδό του. Για παράδειγμα, το jq μορφοποιεί όμορφα από προεπιλογή, οπότε περνώντας JSON στο φίλτρο . παίρνεις δωρεάν όμορφα μορφοποιημένη έξοδο!

$ echo '[1, 2, 3]' | jq '.'
[
  1,
  2,
  3
]

Πίνακες

Αυτή θα είναι μια γρήγορη εισαγωγή στην εργασία με πίνακες. Θα καλύψουμε αυτό το θέμα με περισσότερες λεπτομέρειες αργότερα.

Τα στοιχεία ενός πίνακα προσπελαύνονται με αγκύλες και η αρίθμησή τους ξεκινά από το μηδέν.

$ echo '[10, 20, 30]' | jq '.[1]'
20

Ένα φίλτρο μπορεί να φτιάξει έναν πίνακα τυλίγοντας μια έκφραση σε [ και ]

  • με μια γνωστή λίστα στοιχείων:

    jq -n '[1, 2, 3]'
    
  • για να συλλέξεις μια ροή στοιχείων: για παράδειγμα, η range είναι μια συνάρτηση που παράγει μια ροή αριθμών

    $ jq -n 'range(10; 70; 15)'
    10
    25
    40
    55
    

    Η χρήση του [] συλλέγει τα αποτελέσματα της έκφρασης σε έναν πίνακα

    $ jq -c -n '[range(10; 70; 15)]'
    [10,25,40,55]
    

Το κόμμα είναι τελεστής

Το κόμμα δεν είναι απλώς σύνταξη που χωρίζει τα στοιχεία ενός πίνακα. Το κόμμα είναι ένας τελεστής που ενώνει ροές.

Για παράδειγμα, το [1, 2, 3] είναι ένα φίλτρο που χρησιμοποιεί τον κατασκευαστή πίνακα [] για να συλλέξει το αποτέλεσμα της ένωσης των τριών εκφράσεων 1, 2 και 3.

Πρόσεξες τις άνω τελείες στο range(10; 70; 15) παραπάνω; Επειδή τα κόμματα έχουν συγκεκριμένο σκοπό στη γλώσσα jq, οι συναρτήσεις που δέχονται πολλαπλά ορίσματα χρησιμοποιούν άνω τελείες για να χωρίσουν τα ορίσματα.

Αντικείμενα

Μια γρήγορη εισαγωγή στα αντικείμενα.

Όπως σε πολλές γλώσσες προγραμματισμού, χρησιμοποίησε τελείες για να προσπελάσεις τις ιδιότητες ενός αντικειμένου

$ echo '{"foo": {"bar": "qux"}}' | jq '.foo.bar'
"qux"

Οι αγκύλες μπορούν να χρησιμοποιηθούν και για αντικείμενα, αλλά τότε χρειάζονται εισαγωγικά για τα κυριολεκτικά συμβολοσειρών. Αυτός είναι ένας τρόπος να δουλέψεις με κλειδιά που περιέχουν κενά.

$ echo '{"foo bar": "qux"}' | jq '.["foo bar"]'
"qux"

Μπορείς να κατασκευάσεις ένα αντικείμενο με {} και ζεύγη key: value. Τα εισαγωγικά δεν είναι απαραίτητα γύρω από κλειδιά που είναι "απλές" συμβολοσειρές.

jq -n '{question: (6 * 9), answer: 42}'

παράγει

{
  "question": 54,
  "answer": 42
}

Για να αντιμετωπίσεις το κλειδί ως έκφραση, πρέπει να το τυλίξεις σε παρενθέσεις (το παρακάτω δίνει επίσης το ίδιο αποτέλεσμα όπως παραπάνω).

echo '[["question", "answer"], [54, 42]]' \
| jq '{(.[0][0]): .[1][0], (.[0][1]): .[1][1]}'
Note

Είναι αρκετά συνηθισμένο να θέλεις να εξαγάγεις ένα υποσύνολο κλειδιών από ένα μεγάλο αντικείμενο. Για παράδειγμα, για να εξαγάγεις τα id και name από

{
    "id": 101,
    "name": "alpha widget",
    "specifications": {...}
}

Θα μπορούσαμε να γράψουμε

{id: .id, name: .name}

Αλλά αυτό είναι τόσο συνηθισμένο που υπάρχει συντομευμένη σύνταξη γι' αυτό:

{id, name}

Σωληνώσεις

Για παράδειγμα, δεδομένου του file.json που περιέχει

{
  "key1": "value1",
  "key2": [5, 15, 25]
}

Ας υπολογίσουμε το μήκος του πίνακα key2:

$ jq '.key2 | length' file.json
3

Διοχετεύουμε την έξοδο της έκφρασης .key2 ως είσοδο στη length, η οποία, όπως είναι αναμενόμενο, παράγει τον αριθμό των στοιχείων του πίνακα.

Caution

Αυτή είναι μια πτυχή του jq που θέλει λίγο χρόνο για να τη συνηθίσεις. Οι περισσότερες (αλλά όχι όλες) οι συναρτήσεις συμπεριφέρονται σαν φίλτρα, όπου περνάς δεδομένα στην είσοδο του φίλτρου, όχι ως όρισμα.

Τα φίλτρα μπορούν να αγνοήσουν την είσοδό τους

Σε αυτό το παράδειγμα, τα δεδομένα JSON εισόδου αγνοούνται και δεν έχουν καμία επίδραση στην έξοδο:

$ echo '{"answer": 42}' | jq '6 * 9'
54

Τα φίλτρα μπορούν να παράγουν ροές δεδομένων

Ένα φίλτρο μπορεί να παράγει περισσότερες από μία τιμές. Για παράδειγμα, το φίλτρο .[] παράγει κάθε στοιχείο ενός πίνακα ως ξεχωριστή τιμή:

$ jq -n -c '[1, 2, 3]'
[1,2,3]

$ jq -n -c '[1, 2, 3] | .[]'
1
2
3

Διοχετεύοντας ένα τέτοιο φίλτρο σε ένα άλλο, θα εκτελεστεί το 2ο φίλτρο για κάθε τιμή:

$ jq -n -c '[1, 2, 3] | .[] | . * 2'
2
4
6

Αυτό μοιάζει με έμμεση επανάληψη. Μόλις καταλάβεις αυτήν την τεχνική, θα συνειδητοποιήσεις ότι ισχυρότατα φίλτρα jq μπορούν να είναι πολύ σύντομα.

Παρενθέσεις

Οι παρενθέσεις χρησιμοποιούνται για να ομαδοποιήσουν υποεκφράσεις μαζί, ώστε να επιβληθεί η σειρά των πράξεων, όπως ακριβώς και σε άλλες γλώσσες. Στη jq, η ανάγκη γι' αυτές μπορεί να φαίνεται κάπως αναπάντεχη.

Για παράδειγμα, ας πούμε ότι θέλουμε να κατασκευάσουμε έναν πίνακα με 2 στοιχεία: την τετραγωνική ρίζα του 9 και το e υψωμένο στη δύναμη 1. Οι δύο μεμονωμένες εκφράσεις είναι 9 | sqrt και 1 | exp. Περιμένουμε η έξοδος να είναι ο πίνακας [3, 2.7...]

$ jq -n '[ 9|sqrt, 1|exp ]'
[
  20.085536923187668,
  2.718281828459045
]

Γιατί δεν πήραμε αυτό που περιμέναμε; Το jq το ερμηνεύει ως εξής:

[ ((9|sqrt), 1) | exp ]

Το jq φτιάχνει μια ροή δύο στοιχείων (3 και 1), τα οποία δίνονται το καθένα στο exp.

Πρέπει να διασφαλίσουμε ότι το exp παίρνει μόνο έναν αριθμό ως είσοδο. Με άλλα λόγια, πρέπει να επιβάλουμε ο σωλήνας να αξιολογείται πριν από το κόμμα.

$ jq -n '[ 9|sqrt, (1|exp) ]'
[
  3,
  2.718281828459045
]

Τύποι

Από το εγχειρίδιο

Το jq υποστηρίζει το ίδιο σύνολο τύπων δεδομένων με το JSON: αριθμούς, συμβολοσειρές, Boolean (λογική τιμή), πίνακες, αντικείμενα (τα οποία στην ορολογία του JSON είναι hashes με κλειδιά μόνο συμβολοσειρών) και "null".

Θα μάθεις περισσότερα γι' αυτά σε επόμενες ασκήσεις.

Κενά διαστήματα

Τα κενά διαστήματα δεν είναι σημαντικά στη jq. Χρησιμοποίησε κενά, στηλοθέτες και αλλαγές γραμμής όπως θέλεις για να μορφοποιήσεις τον κώδικά σου. Δεν γνωρίζουμε να υπάρχει κανένας οδηγός στυλ για τη jq.

Αμετάβλητες τιμές

Οι τιμές στη jq είναι αμετάβλητες. Τα φίλτρα που τροποποιούν μια τιμή θα παράγουν μια νέα τιμή. Αυτό σημαίνει ότι η jq δεν έχει καθολικές μεταβλητές. Θα πρέπει να συνηθίσεις να περνάς κατάσταση από το ένα φίλτρο στο άλλο.

"Αληθότητα"

Οι τιμές false και null θεωρούνται ψευδείς. Οποιαδήποτε άλλη τιμή (συμπεριλαμβανομένου του αριθμού μηδέν και της κενής συμβολοσειράς/πίνακα/αντικειμένου) είναι αληθής.

Συναρτήσεις και τελεστές

Χωρίς να μπούμε σε μεγάλο βάθος (οι συναρτήσεις θα είναι θέμα άλλης άσκησης), ορίστε μερικές χρήσιμες ενσωματωμένες συναρτήσεις:

  • length

    Δεδομένου ενός πίνακα ως είσοδο, παράγει τον αριθμό των στοιχείων του πίνακα.

    $ jq -n '[10, 20, 30, 40] | length'
    4
    
  • +

    Αυτός ο τελεστής κάνει διαφορετικά πράγματα ανάλογα με τον τύπο των τελεστέων του: προσθέτει αριθμούς, συνενώνει συμβολοσειρές, προσθέτει στοιχεία σε πίνακες, συγχωνεύει αντικείμενα.

    $ jq -c -n '
        3 + 4,
        "foo" + "bar",
        ["a", "b"] + ["c"],
        {"m": 10} + {"n": 20}
    '
    7
    "foobar"
    ["a","b","c"]
    {"m":10,"n":20}
    

    Η add είναι μια συνάρτηση που παίρνει έναν πίνακα και επιστρέφει ένα στοιχείο με όλα τα στοιχεία αθροισμένα μεταξύ τους με τους κανόνες του +. Το [1, 2, 3] | add παράγει 6.

  • map

    Δεδομένου ενός πίνακα ως είσοδο και ενός φίλτρου ως όρισμα, παράγει έναν πίνακα όπου το φίλτρο εφαρμόζεται σε κάθε στοιχείο

    $ jq -c -n '[10, 20, 30, 40] | map(. / 5)'
    [2,4,6,8]
    
  • select

    Δεδομένης κάποιας εισόδου και ενός φίλτρου ως όρισμα:

    • αν το φίλτρο που εφαρμόζεται στο όρισμα έχει ως αποτέλεσμα μια αληθή τιμή, παράγει την είσοδο αμετάβλητη
    • διαφορετικά, δεν παράγει τίποτα (όχι την τιμή null, αλλά πραγματικά καμία έξοδο)

    Για παράδειγμα, δεδομένων κάποιων αριθμών, επίλεξε αυτούς που διαιρούνται με το 3

    $ jq -n 'range(10) | select(. % 3 == 0)'
    0
    3
    6
    9
    

    Θυμήσου ότι η range παράγει μια ροή αριθμών. Η select θα καλείται μία φορά για κάθε αριθμό. Μόνο οι αριθμοί που "περνούν" την έκφραση παράγονται.

    Συχνά χρειάζεται να επιλέξεις στοιχεία ενός πίνακα. Υπάρχουν μερικοί τρόποι να το κάνεις αυτό.

    Με είσοδο ["Anne", "Bob", "Cathy", "Dave"], επίλεξε τα ονόματα που έχουν μήκος 4.

    • χρησιμοποίησε τις map και select μαζί

      map(select(length == 4))
      
    • σπάσε τον πίνακα στα στοιχεία του, εφάρμοσε select σε αυτή τη ροή και συγκέντρωσε τα αποτελέσματα

      [ .[] | select(length == 4) ]
      

Σχόλια

Τα σχόλια ξεκινούν με τον χαρακτήρα # και συνεχίζουν μέχρι το τέλος της γραμμής.

Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα

Μάθε την έννοια Τα βασικά