Kurzusok
/
jq
jq
/
Feladatok
/
Reguláris chatbot
Reguláris chatbot

Reguláris chatbot

Tanulófeladat

Bevezetés

Reguláris kifejezések

A reguláris kifejezések (regexek) olyan karaktersorozatok, amelyek egy szövegben megkeresendő mintát írnak le.

A reguláris kifejezések szintaxisának megtanulása meghaladja ennek a témának a kereteit. Arra összpontosítunk, hogy milyen kifejezéseket kínál a jq a regexek használatához.

A reguláris kifejezések változatai

A különböző eszközök a reguláris kifejezések különböző változatait valósítják meg. A jq az Oniguruma regexkönyvtárat használja, amely nagyrészt kompatibilis a Perl v5.8 regexeivel.

A jq által használt konkrét szintaxis az Oniguruma GitHub-tárolójában található.

Caution

A jq-nak nincs különleges szintaxisa a reguláris kifejezésekhez. Azokat egyszerűen stringként fejezzük ki. Ez azt jelenti, hogy a reguláris kifejezésben minden fordított perjelet escape-elni kell a stringben.

Például a számjegyet jelölő karakterosztályt (\d) így kell írni: "\\d".

Regexfüggvények

A jq-ban a reguláris kifejezések használata néhány szűrőre korlátozódik.

Egyszerű illesztés

Ha tudni szeretnéd, hogy egy string illeszkedik-e egy mintára, használd a test szűrőt.

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

Ez a szűrő Boolean eredményt ad vissza.

"Hello World!" | test("W")    # => true
"Goodbye Mars" | test("W")    # => false
Információk az illesztésről

Ha ki szeretnéd nyerni azt a részstringet, amely ténylegesen illeszkedett a mintára, használd a match szűrőt.

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

Ez a szűrő a következőt adja vissza:

  • semmit, ha nem volt illesztés, vagy
  • egy objektumot, amely különféle tulajdonságokat tartalmaz, ha volt illesztés.

Ez a példa két azonos, egymást követő magánhangzót keres a visszahivatkozás szintaxisával, \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
#        }
#      ]
#    }

A match szűrő minden illesztéshez egy objektumot ad vissza. Ez a példa a "g" jelző működését mutatja be, amellyel az összes magánhangzót megtalálhatod.

"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": [] }
Rögzített részstringek

A match szűrőhöz hasonlóan a capture szűrő is egy objektumot ad vissza, ha volt illesztés.

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

A visszaadott objektum a nevesített rögzítések leképezése.

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

A scan szűrő hasonló a match szűrőhöz a "g" jelzővel.

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

A scan részstringek folyamát adja vissza.

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

A részstringek rögzítéséhez használd a [...] tömbkonstruktort.

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

Ha tudod, hogy a string mely részeit szeretnéd megtartani, használd a match vagy a scan szűrőt. Ha tudod, hogy mely részeit szeretnéd elvetni, használd a split szűrőt.

STRING | split(REGEX; FLAGS)
Caution

Az egyargumentumos split szűrő a paraméterét rögzített stringként kezeli.

Ahhoz, hogy regexet használj a split-tel, meg kell adnod a második argumentumot; nyugodtan használhatsz üres stringet.

Egy példa, amely egy stringet tetszőleges whitespace mentén bont fel.

"first   second           third fourth" | split("\\s+"; "")
# => ["first", "second", "third", "fourth"]
Helyettesítések

A sub és a gsub szűrő át tudja alakítani a bemeneti stringet: a bemenet illeszkedő részeit egy helyettesítő stringgel cseréli le.

Ha csak az első illesztést szeretnéd lecserélni, használd a sub szűrőt. Ha az összes illesztést le szeretnéd cserélni, használd a gsub szűrőt.

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."

A helyettesítő szöveg hivatkozhat az illeszkedő részstringekre; használj nevesített rögzítéseket és string-interpolációt.

"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"

Jelzők

A fenti szűrők mindegyikében a FLAGS egy string, amely a támogatott jelzők közül nullát vagy többet tartalmaz.

  • g - Globális keresés (az összes illesztést megtalálja, nem csak az elsőt)
  • i - Kis- és nagybetűt nem megkülönböztető keresés
  • m - Többsoros mód (a '.' az újsorokra is illeszkedik)
  • n - Az üres illesztések figyelmen kívül hagyása
  • p - Az s és az m mód is engedélyezve van
  • s - Egysoros mód ('^' -> '\A', '$' -> '\Z')
  • l - A lehető leghosszabb illesztések keresése
  • x - Kiterjesztett regexformátum (a whitespace-t és a megjegyzéseket figyelmen kívül hagyja)

Például

"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")

Utasítások

Felvettek reguláris kifejezés szakértőnek egy olyan céghez, amelyik egy Chatbotot fejleszt.

A fejlesztés nagyon kezdeti szakaszában tart. A küldetésed, hogy reguláris kifejezésekkel javítsd a Chatbot képességét a természetes nyelv megértésére és előállítására.

1. Érvényes parancs ellenőrzése

A Chatbot nemcsak okos, hanem hűséges asszisztens is. Ahhoz, hogy kérdezz valamit a Chatbottól, a felhasználónak a parancs legelején ki kell mondania a „Chatbot” szót. Nem számít, hogy a kulcsszó csupa nagy- vagy csupa kisbetűvel szerepel. A lényeg, hogy a szó hol áll.

Valósítsd meg az is_valid_command függvényt, amely segít a Chatbotnak felismerni, amikor a felhasználó parancsot ad.

"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

2. Titkosított emojik eltávolítása

A Chatbot nehezen érti meg, hogyan használják az emberek az emojikat az érzelmeik kifejezésére. Amikor a Chatbot felhasználói üzeneteket kap, minden emoji „emoji” stringként jelenik meg, amelyet egy azonosítószám követ.

Valósítsd meg a remove_emoji függvényt, amely egy stringet kap, és eltávolítja az összes emojit az üzenetből.

Az emojit nem tartalmazó sorokat változatlanul kell visszaadni. Csak az emoji stringet távolítsd el. A szóközöket ne igazítsd.

"I love playing videogames emoji3465 it's one of my hobbies" | remove_emoji
# => "I love playing videogames  it's one of my hobbies"

3. Érvényes telefonszám ellenőrzése

A Chatbottal folytatott beszélgetés során előbb-utóbb megadja a felhasználó a telefonszámát. A Chatbot csak egy meghatározott formátumú számot tud hívni.

Valósítsd meg a check_phone_number függvényt.

Ha a szám érvényes, a Chatbot egy üzenettel válaszol, amelyben megköszöni a felhasználónak, és megerősíti a számot. Ha a szám érvénytelen, a Chatbot tájékoztatja a felhasználót, hogy a telefonszám nem érvényes.

A várt formátum a (+NN) NNN-NNN-NNN, ahol az N egy számjegyet jelöl.

"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."

A Chatbot igazán kíváncsi szoftver. Bár képes az interneten rákeresni egy adott témára, szeret megkérdezni felhasználókat menő weboldalakról, ahol releváns információkat találhat.

Példa egy beszélgetésre:

Chatbot: Szia, felhasználó! Meg szeretném tanulni, hogyan kell JavaScriptben programozni. Tudsz valami menő weboldalt, ahol tanulhatnék?

Felhasználó: Sokat tanultam az exercism.org oldalról, rengeteg nagyszerű dolog van ott.

Valósítsd meg a get_domains függvényt, amely a weboldalak domainjeit tartalmazó tömböt adja vissza.

"I learned a lot from exercism.org and google.com" | get_domains
# => ["exercism.org", "google.com"]

5. Üdvözöld a felhasználót

Egy udvarias Chatbot a nevükön szólítja a felhasználókat. Amikor egy felhasználó bemutatkozik, a Chatbotunk felismeri a nevét, és barátságos üdvözléssel válaszol.

Írd meg a nice_to_meet_you függvényt.

Ha a bemeneti string tartalmazza a „My name is Someone.” szöveget, keresd ki a nevet, és add vissza a „Nice to meet you, Someone.” stringet.

"My name is Jean-Luc" | nice_to_meet_you
# => "Nice to meet you, Jean-Luc"

6. Nagyon egyszerű CSV-feldolgozás

Engedve a „funkciótúltengésnek”, hozzáadunk a Chatbothoz egy CSV-feldolgozó függvényt.

Valósítsd meg a parse_csv függvényt, amely egy stringet kap, és a keletkező mezők tömbjét adja vissza. A mezőelválasztó „vessző, amelyet opcionális szóköz követ” legyen.

A CSV-formátum egyetlen speciális esetével sem foglalkozunk (például az olyan mezőkkel, amelyek vesszőt tartalmaznak).

"first, second,third,   fourth" | parse_csv
# => ["first", "second", "third", "fourth"]
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
jq Exercism

Készen állsz elkezdeni a(z) Reguláris chatbot feladatot?

Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) jq nyelvet 12 fogalom75 feladat segítségével, valódi emberi mentorálással, mindez ingyen.