Reguläre Ausdrücke (Regexes) sind Zeichenfolgen, die ein Suchmuster in einem Text beschreiben.
Die Syntax regulärer Ausdrücke zu lernen, geht über den Rahmen dieses Themas hinaus.
Wir konzentrieren uns auf die Ausdrücke, die jq bereitstellt, um Regexes zu nutzen.
Verschiedene Werkzeuge implementieren unterschiedliche Versionen regulärer Ausdrücke.
jq verwendet die Regex-Bibliothek Oniguruma, die weitgehend mit den regulären Ausdrücken von Perl v5.8 kompatibel ist.
Die konkrete Syntax, die jq verwendet, findest du im Oniguruma-Repository auf GitHub.
jq hat keine besondere Syntax für reguläre Ausdrücke.
Sie werden einfach als Strings ausgedrückt.
Das bedeutet, dass alle Backslashes im regulären Ausdruck im String escapt werden müssen.
Zum Beispiel muss die Zeichenklasse für Ziffern (\d) als "\\d" geschrieben werden.
Reguläre Ausdrücke in jq sind auf eine Reihe von Filtern beschränkt.
Wenn du wissen möchtest, ob ein String zu einem Muster passt, verwendest du den test-Filter.
STRING | test(REGEX)
STRING | test(REGEX; FLAGS)
STRING | test([REGEX, FLAGS])
Dieser Filter gibt ein boolesches Ergebnis aus.
"Hello World!" | test("W") # => true
"Goodbye Mars" | test("W") # => false
Wenn du den Teilstring extrahieren möchtest, der tatsächlich zum Muster gepasst hat, verwendest du den match-Filter.
STRING | match(REGEX)
STRING | match(REGEX; FLAGS)
STRING | match([REGEX, FLAGS])
Dieser Filter gibt aus:
Dieses Beispiel sucht mit der Backref-Syntax \1 nach zwei aufeinanderfolgenden gleichen Vokalen.
"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
# }
# ]
# }
Der match-Filter gibt für jeden Treffer ein Objekt zurück.
Dieses Beispiel zeigt das Flag "g" in Aktion, um alle Vokale zu finden.
"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": [] }
Ähnlich wie der match-Filter gibt der capture-Filter ein Objekt zurück, wenn es einen Treffer gab.
STRING | capture(REGEX)
STRING | capture(REGEX; FLAGS)
STRING | capture([REGEX, FLAGS])
Das zurückgegebene Objekt ist eine Zuordnung der benannten Captures.
"JIRAISSUE-1234" | capture("(?<project>\\w+)-(?<issue_num>\\d+)")
# => {
# "project": "JIRAISSUE",
# "issue_num": "1234"
# }
Der scan-Filter ähnelt match mit dem Flag "g".
STRING | scan(REGEX)
STRING | scan(REGEX; FLAGS)
scan gibt einen Stream von Teilstrings aus.
"Goodbye Mars" | scan("[aeiou]")
# => "o"
# "o"
# "e"
# "a"
Verwende den Array-Konstruktor [...], um die Teilstrings zu erfassen.
"Goodbye Mars" | [ scan("[aeiou]") ]
# => ["o", "o", "e", "a"]
Wenn du die Teile des Strings kennst, die du behalten möchtest, verwende match oder scan.
Wenn du die Teile kennst, die du verwerfen möchtest, verwende split.
STRING | split(REGEX; FLAGS)
Der split-Filter mit einem Argument (1-arity) behandelt sein Argument als festen String.
Um mit split einen regulären Ausdruck zu verwenden, musst du das zweite Argument angeben; eine leere Zeichenkette ist in Ordnung.
Ein Beispiel, das einen String an beliebigem Leerraum aufteilt.
"first second third fourth" | split("\\s+"; "")
# => ["first", "second", "third", "fourth"]
Die Filter sub und gsub können den Eingabe-String umwandeln, indem sie die übereinstimmenden Teile der Eingabe durch einen Ersatz-String ersetzen.
Um nur den ersten Treffer zu ersetzen, verwende sub.
Um alle Treffer zu ersetzen, verwende 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."
Der Ersatztext kann sich auf die übereinstimmenden Teilstrings beziehen; verwende benannte Captures und String-Interpolation.
"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"
In allen oben genannten Filtern ist FLAGS ein String, der aus null oder mehr der unterstützten Flags besteht.
g - Globale Suche (alle Treffer finden, nicht nur den ersten)i - Suche ohne Beachtung der Groß-/Kleinschreibungm - Mehrzeilenmodus ('.' passt auch auf Zeilenumbrüche)n - Leere Treffer ignorierenp - Sowohl der s- als auch der m-Modus sind aktivierts - Einzeilenmodus ('^' -> '\A', '$' -> '\Z')l - Die längstmöglichen Treffer findenx - Erweitertes Regex-Format (Leerraum und Kommentare ignorieren)Zum Beispiel
"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")
Du wurdest als Spezialist für reguläre Ausdrücke in einem Unternehmen eingestellt, das einen Chatbot entwickelt.
Er befindet sich in einer sehr frühen Entwicklungsphase. Deine Aufgabe ist es, reguläre Ausdrücke zu verwenden, um die Fähigkeit des Chatbots zu verbessern, natürliche Sprache zu verstehen und zu erzeugen.
Der Chatbot ist nicht nur schlau, sondern auch ein loyaler Assistent. Um den Chatbot etwas zu fragen, muss der Benutzer das Wort „Chatbot“ an der ersten Position des Befehls sagen. Es spielt keine Rolle, ob das Schlüsselwort in Groß- oder Kleinbuchstaben steht. Wichtig ist die Position des Wortes.
Implementiere die Funktion is_valid_command, die dem Chatbot hilft zu erkennen, wann der Benutzer einen Befehl gibt.
"Chatbot, play a song from the 80's." | is_valid_command
# => true
"Hey Chatbot, where is the closest pharmacy?" | is_valid_command
# => false
"CHATBOT, do you have a solution for this challenge?" | is_valid_command
# => true
Der Chatbot hat Schwierigkeiten zu verstehen, wie Menschen Emojis verwenden, um ihre Gefühle auszudrücken. Wenn der Chatbot Nachrichten von Benutzern empfängt, wird jedes Emoji als der String „emoji“ dargestellt, gefolgt von einer ID-Nummer.
Implementiere die Methode remove_emoji, die einen String entgegennimmt und alle Emojis aus der Nachricht entfernt.
Zeilen, die keine Emojis enthalten, sollen unverändert zurückgegeben werden. Entferne einfach den String „emoji“. Verändere die Leerzeichen nicht.
"I love playing videogames emoji3465 it's one of my hobbies" | remove_emoji
# => "I love playing videogames it's one of my hobbies"
Irgendwann während der Interaktion mit dem Chatbot gibt der Benutzer eine Telefonnummer an. Der Chatbot kann nur Nummern in einem bestimmten Format anrufen.
Implementiere die Funktion check_phone_number.
Wenn die Nummer gültig ist, antwortet der Chatbot mit einer Nachricht, in der er sich beim Benutzer bedankt und die Nummer bestätigt. Wenn die Nummer ungültig ist, teilt der Chatbot dem Benutzer mit, dass die Telefonnummer nicht gültig ist.
Das erwartete Format ist (+NN) NNN-NNN-NNN, wobei N eine Ziffer ist.
"chatbot my phone number is (+34) 659-771-594" | check_phone_number
# => "Thanks! Your phone number is OK."
"chatbot, call me at 659-771-594" | check_phone_number
# => "Oops, it seems like I can't reach out to 659-771-594."
Der Chatbot ist eine wirklich neugierige Software. Obwohl er das Internet nach einem bestimmten Thema durchsuchen kann, fragt er Benutzer gern nach coolen Websites, die sie besuchen können, um relevante Informationen zu finden.
Beispielgespräch:
Chatbot: Hey Benutzer, ich würde gern lernen, wie man in JavaScript programmiert. Kennst du eine coole Website, auf der ich das lernen kann?
Benutzer: Ich habe viel auf exercism.org gelernt, dort gibt es jede Menge großartige Sachen.
Implementiere die Funktion get_domains, die ein Array von Website-Domains zurückgibt.
"I learned a lot from exercism.org and google.com" | get_domains
# => ["exercism.org", "google.com"]
Ein höflicher Chatbot spricht Benutzer mit ihrem Namen an. Wenn ein Benutzer sich vorstellt, erkennt unser Chatbot seinen Namen und antwortet mit einer freundlichen Begrüßung.
Schreibe die Funktion nice_to_meet_you.
Wenn der Eingabe-String „My name is Someone.“ enthält, erfasse den Namen und gib den String „Nice to meet you, Someone.“ zurück.
"My name is Jean-Luc" | nice_to_meet_you
# => "Nice to meet you, Jean-Luc"
Weil wir uns der „schleichenden Funktionswut“ beugen, fügen wir dem Chatbot eine Funktion zum Parsen von CSV hinzu.
Implementiere die Funktion parse_csv, die einen String entgegennimmt und ein Array der resultierenden Felder zurückgibt.
Der Feldtrenner soll „Komma plus optionaler Leerraum“ sein.
Wir kümmern uns nicht um die Randfälle des CSV-Formats (etwa Felder, die Kommas enthalten).
"first, second,third, fourth" | parse_csv
# => ["first", "second", "third", "fourth"]
Melde dich bei Exercism an, um jq mit 12 Konzepte75 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.