Διαδρομές
/
jq
jq
/
Ύλη
/
Κανονικές εκφράσεις
Κα

Κανονικές εκφράσεις σε jq

1 άσκηση

Σχετικά με την έννοια Κανονικές εκφράσεις

Οι κανονικές εκφράσεις (regex) είναι ακολουθίες χαρακτήρων που ορίζουν ένα μοτίβο αναζήτησης μέσα σε κείμενο.

Η εκμάθηση της σύνταξης των κανονικών εκφράσεων ξεπερνά τα όρια αυτού του θέματος. Θα επικεντρωθούμε στις εκφράσεις που παρέχει το jq για να αξιοποιείς τις κανονικές εκφράσεις.

Παραλλαγές κανονικών εκφράσεων

Διαφορετικά εργαλεία υλοποιούν διαφορετικές εκδόσεις των κανονικών εκφράσεων. Το jq ενσωματώνει τη βιβλιοθήκη κανονικών εκφράσεων Oniguruma, η οποία είναι σε μεγάλο βαθμό συμβατή με τις κανονικές εκφράσεις της Perl v5.8.

Η συγκεκριμένη σύνταξη που χρησιμοποιεί το jq βρίσκεται στο αποθετήριο GitHub του Oniguruma.

Caution

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

Για παράδειγμα, η κλάση χαρακτήρων για ψηφία (\d) πρέπει να γραφτεί ως "\\d".

Συναρτήσεις κανονικών εκφράσεων

Οι κανονικές εκφράσεις στο jq περιορίζονται σε ένα σύνολο φίλτρων.

Απλή αντιστοίχιση

Όταν θέλεις να μάθεις αν μια συμβολοσειρά ταιριάζει με ένα μοτίβο, χρησιμοποίησε το φίλτρο test.

STRING | test(REGEX)
STRING | test(REGEX; FLAGS)
STRING | test([REGEX, FLAGS])

Αυτό το φίλτρο βγάζει ένα αποτέλεσμα Boolean.

"Hello World!" | test("W")    # => true
"Goodbye Mars" | test("W")    # => false

Πληροφορίες για την αντιστοίχιση

Όταν θέλεις να εξαγάγεις την υποσυμβολοσειρά που όντως ταίριαξε με το μοτίβο, χρησιμοποίησε το φίλτρο match.

STRING | match(REGEX)
STRING | match(REGEX; FLAGS)
STRING | match([REGEX, FLAGS])

Αυτό το φίλτρο βγάζει:

  • τίποτα, αν δεν υπήρξε αντιστοίχιση, ή
  • ένα αντικείμενο που περιέχει διάφορες ιδιότητες, αν υπήρξε αντιστοίχιση.

Αυτό το παράδειγμα ψάχνει δύο ίδια συνεχόμενα φωνήεντα, χρησιμοποιώντας τη σύνταξη backreference, \1.

"Hello World!" | match("([aeiou])\\1")
# => empty

"Goodbye Mars" | match("([aeiou])\\1")
# => {
#      "offset": 1,
#      "length": 2,
#      "string": "oo",
#      "captures": [
#        {
#          "offset": 1,
#          "length": 1,
#          "string": "o",
#          "name": null
#        }
#      ]
#    }

Το φίλτρο match επιστρέφει ένα αντικείμενο για κάθε αντιστοίχιση. Αυτό το παράδειγμα δείχνει τη σημαία "g" σε δράση, για να βρει όλα τα φωνήεντα.

"Goodbye Mars" | match("[aeiou]"; "g")
# => { "offset": 1, "length": 1, "string": "o", "captures": [] }
#    { "offset": 2, "length": 1, "string": "o", "captures": [] }
#    { "offset": 6, "length": 1, "string": "e", "captures": [] }
#    { "offset": 9, "length": 1, "string": "a", "captures": [] }

Υποσυμβολοσειρές που συλλαμβάνονται

Παρόμοια με το φίλτρο match, το φίλτρο capture επιστρέφει ένα αντικείμενο αν υπήρξε αντιστοίχιση.

STRING | capture(REGEX)
STRING | capture(REGEX; FLAGS)
STRING | capture([REGEX, FLAGS])

Το αντικείμενο που επιστρέφεται είναι μια αντιστοίχιση των ονομασμένων συλλήψεων.

"JIRAISSUE-1234" | capture("(?<project>\\w+)-(?<issue_num>\\d+)")
# => {
#      "project": "JIRAISSUE",
#      "issue_num": "1234"
#    }

Μόνο οι υποσυμβολοσειρές

Το φίλτρο scan είναι παρόμοιο με το match με τη σημαία "g".

STRING | scan(REGEX)
STRING | scan(REGEX; FLAGS)

# note, there is no scan([REGEX, FLAGS]) version, unlike other filters

Το scan θα βγάλει μια ροή υποσυμβολοσειρών.

"Goodbye Mars" | scan("[aeiou]")
# => "o"
#    "o"
#    "e"
#    "a"

Χρησιμοποίησε τον κατασκευαστή πίνακα [...] για να συλλάβεις τις υποσυμβολοσειρές.

"Goodbye Mars" | [ scan("[aeiou]") ]
# => ["o", "o", "e", "a"]

Διαχωρισμός συμβολοσειράς

Αν ξέρεις ποια μέρη της συμβολοσειράς θέλεις να κρατήσεις, χρησιμοποίησε το match ή το scan. Αν ξέρεις ποια μέρη θέλεις να πετάξεις, χρησιμοποίησε το split.

STRING | split(REGEX; FLAGS)
Caution

Το φίλτρο split με ένα όρισμα αντιμετωπίζει το όρισμά του ως σταθερή συμβολοσειρά.

Για να χρησιμοποιήσεις κανονική έκφραση με το split, πρέπει να δώσεις το δεύτερο όρισμα· δεν πειράζει να χρησιμοποιήσεις μια κενή συμβολοσειρά.

Ένα παράδειγμα που χωρίζει μια συμβολοσειρά σε αυθαίρετα κενά.

"first   second           third fourth" | split("\\s+"; "")
# => ["first", "second", "third", "fourth"]
Note

Αυτό συμβαίνει αν ξεχάσουμε το όρισμα με τις σημαίες.

"first   second           third fourth" | split("\\s+")
# => ["first   second           third fourth"]

Μόνο ένα αποτέλεσμα: η σταθερή συμβολοσειρά \s+ δεν βρέθηκε στην είσοδο.

Το split με ένα όρισμα δεν μπορεί να χειριστεί αυθαίρετα κενά. Ο διαχωρισμός με βάση το κενό δίνει αυτό το αποτέλεσμα.

"first   second           third fourth" | split(" ")
# => ["first", "", "", "second", "", "", "", "",
#     "", "", "", "", "", "", "third", "fourth" ]

Αντικαταστάσεις

Τα φίλτρα sub και gsub μπορούν να μετασχηματίσουν τη συμβολοσειρά εισόδου, αντικαθιστώντας τα τμήματα της εισόδου που ταιριάζουν με μια συμβολοσειρά αντικατάστασης.

Για να αντικαταστήσεις μόνο την πρώτη αντιστοίχιση, χρησιμοποίησε το sub. Για να αντικαταστήσεις όλες τις αντιστοιχίσεις, χρησιμοποίησε το gsub.

STRING | sub(REGEX; REPLACEMENT)
STRING | sub(REGEX; REPLACEMENT; FLAGS)
STRING | gsub(REGEX; REPLACEMENT)
STRING | gsub(REGEX; REPLACEMENT; FLAGS)
"Goodnight kittens. Goodnight mittens." | sub("night"; " morning")
# => "Good morning kittens. Goodnight mittens."

"Goodnight kittens. Goodnight mittens." | gsub("night"; " morning")
# => "Good morning kittens. Good morning mittens."

Το κείμενο αντικατάστασης μπορεί να αναφέρεται στις υποσυμβολοσειρές που ταίριαξαν· χρησιμοποίησε ονομασμένες συλλήψεις και παρεμβολή συμβολοσειρών.

"Some 3-letter acronyms: gnu, csv, png"
| gsub( "\\b(?<tla>[[:alpha:]]{3})\\b";     # find words 3 letters long
        "\(.tla | ascii_upcase)" )          # upper-case the match
# => "Some 3-letter acronyms: GNU, CSV, PNG"

Σημαίες

Σε όλα τα παραπάνω φίλτρα, το FLAGS είναι μια συμβολοσειρά που αποτελείται από μηδέν ή περισσότερες από τις υποστηριζόμενες σημαίες.

  • g - Καθολική αναζήτηση (βρίσκει όλες τις αντιστοιχίσεις, όχι μόνο την πρώτη)
  • i - Αναζήτηση χωρίς διάκριση πεζών-κεφαλαίων
  • m - Λειτουργία πολλαπλών γραμμών (το '.' θα ταιριάζει και με αλλαγές γραμμής)
  • n - Αγνόηση κενών αντιστοιχίσεων
  • p - Ενεργοποιούνται και οι δύο λειτουργίες, s και m
  • s - Λειτουργία μονής γραμμής ('^' -> '\A', '$' -> '\Z')
  • l - Βρίσκει τις μεγαλύτερες δυνατές αντιστοιχίσεις
  • x - Εκτεταμένη μορφή κανονικής έκφρασης (αγνοεί τα κενά και τα σχόλια)

Για παράδειγμα

"JIRAISSUE-1234" | capture("(?<project>\\w+)-(?<issue_num>\\d+)")

# or with Extended formatting

"JIRAISSUE-1234" | capture("
                     (?<project>   \\w+ )  # the Jira project
                     -                     # followed by a hyphen
                     (?<issue_num> \\d+ )  # followed by digits
                   "; "x")
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα

Μάθε την έννοια Κανονικές εκφράσεις

Η εξάσκηση είναι κλειδωμένη

Ξεκλείδωσε 1 ακόμη άσκηση για να εξασκηθείς στην έννοια Κανονικές εκφράσεις