{ "metadata": { "language": "ruby", "name": "", "signature": "sha256:2bd0b97db81091dc04afd1bc061506ed5b1d97d0e3f83f0b0a2ddffdd0c84cdb" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Wyra\u017cenia regularne" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wyra\u017cenia regularne s\u0105 bardzo powszechnie wykorzystywane w programowaniu aplikacji internetowych. S\u0105 to wzorce, kt\u00f3re dopasowywane s\u0105 do napis\u00f3w. Mog\u0105 by\u0107 wykorzystywane np. do weryfikacji poprawno\u015bci napis\u00f3w (np. kodu pocztowego, numeru telefonu, nazwiska) ale r\u00f3wnie\u017c do wydostawania pewnych informacji ze z\u0142o\u017conych napis\u00f3w.\n", "\n", "Wyra\u017cenia regularne zapisywane s\u0105 z wykorzystaniem uko\u015bnik\u00f3w np. nast\u0119puj\u0105ce wyra\u017cenie pasuje do napisu zawieraj\u0105cego co najmniej \n", "jedn\u0105 liter\u0119 'a'\n", "```ruby\n", "/a/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dopasowania napisu do wyra\u017cenia mo\u017ce by\u0107 weryfikowane na dwa sposoby. Po pierwsze mo\u017cna skorzysta\u0107 z operatora dopasowania `=~`\n", "```ruby\n", "\"Ala ma kota\" =~ /a/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"Ala ma kota\" =~ /x/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Warto\u015b\u0107 zwracana przy dopasowaniu to indeks pierwszego dopasowanego znaku. Je\u015bli dopasowanie si\u0119 nie powiod\u0142o zwracana jest warto\u015b\u0107 `nil`. Dzi\u0119ki temu dopasowanie wyra\u017ce\u0144 w tej formie cz\u0119sto wykorzystywane jest w instrukcji warunkwej.\n", "\n", "Drugi spos\u00f3b dopasowania to u\u017cycie metody `match` zdefiniowanej dla wyra\u017ce\u0144 regularnych\n", "```ruby\n", "/a/.match(\"Ala ma kota\")\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dla tej metody zwracany jest jednak nie indeks, ale obiekt klasy `MatchData`, kt\u00f3ry pozwala \"odpyta\u0107\" jak dok\u0142adnie wygl\u0105da dopasowanie\n", "```ruby\n", "matched = /a/.match(\"Ala ma kota\")\n", "matched.begin(0)\n", "matched.end(0)\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 19 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Argument przekazywany do metod `begin` oraz `end` oznaczna indeks dopasowanej \"podgrupy\" wyra\u017cenia. Indeks 0 oznaczna \n", "ca\u0142e dopasowanie." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Zadanie 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Jak my\u015blisz, dlaczego w przypadku dopasowania \u0142a\u0144cucha do wyra\u017cenia zwracany jest indeks pierwszego dopasowanego znaku, a w przypadku niedopasowania, warto\u015b\u0107 `nil`?" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Znaki specjalne" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "W wyra\u017ceniach regularnych poza zwyk\u0142ymi znakami wyst\u0119puj\u0105 znaki specjalne\n", "\n", "| Znak specjalny | Znaczenie |\n", "|----------------|-----------|\n", "| . | dowolny znak |\n", "| | | alternatywa |\n", "| ( | pocz\u0105tek podgrupy |\n", "| ) | koniec podgrupy |\n", "| [ | zakres warto\u015bci |\n", "| { | krotno\u015b\u0107 |\n", "| * | zero lub wi\u0119cej wyst\u0105pie\u0144 |\n", "| + | jedno lub wi\u0119cej wyst\u0105pie\u0144 |\n", "| ? | zero lub jedno wyst\u0105pienie |\n", "| \\ | znak wymazuj\u0105cy znaczenie znaku specjalnego |\n", "| ^ | pocz\u0105tek linii |\n", "| $ | koniec linii |\n", "\n", "\n", "Je\u015bli chcemy aby te znaki zosta\u0142y dopasowane bezpo\u015brednio, musimy poprzedzi\u0107 je odwrotnym uko\u015bnikiem. Poni\u017csze dopasowanie dopasuje si\u0119\u00a0do dowolnego znaku:\n", "```ruby\n", "\"a\" =~ /./\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Je\u015bli chcemy dopasowa\u0107 kropk\u0119, musimy u\u017cy\u0107 odwrotnego uko\u015bnika\n", "\n", "```ruby\n", "\"a\" =~ /\\./\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\".\" =~ /\\./\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatywa dopasowuje si\u0119 do wyra\u017cenia po prawej lub wyra\u017cenia po lewej stronie\n", "```ruby\n", "\"ma\u0142y\" =~ /ma\u0142y|du\u017cy/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"du\u017cy\" =~ /ma\u0142y|du\u017cy/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"wielki\" =~ /ma\u0142y|du\u017cy/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podgrupy pozwalaj\u0105 na wyodr\u0119bnianie pewnych informacji z dopasowanego \u0142a\u0144cucha. Przyk\u0142adowo, je\u015bli z adresu chcemy \n", "wyodr\u0119bni\u0107 kod i miejscowo\u015b\u0107 mo\u017cemy u\u017cy\u0107 nast\u0119puj\u0105cego wyra\u017cenia:\n", "```ruby\n", "matched = /(\\d\\d-\\d\\d\\d) (\\w+)/.match(\"00-700 Warszawa, ul. Kr\u00f3tka 5\")\n", "matched[1]\n", "matched[2]\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 22 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pierwsza dopasowana podgrupa obejmuje kod pocztowy, a druga - nazw\u0119 miejscowo\u015bci. " ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Zadanie 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Napisz wyra\u017cenie, kt\u00f3re dopasowuje si\u0119 do numeru telefonicznego z kodem kierunkowym wojew\u00f3dztwa. U\u017cyj podgrup, aby wydosta\u0107 kod kierunkowy z pe\u0142nego numeru telefonu. Przyk\u0142adowe numer: \"12 2 123 123\", \"22 23 32 654\"" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Klasy znak\u00f3w" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "W powy\u017cszym przyk\u0142adzie wykorzystali\u015bmy tzw. klasy znak\u00f3w `\\d` oraz `\\w`. Klasy te reprezentuj\u0105 grupy znak\u00f3w, kt\u00f3re cz\u0119sto pojawiaj\u0105 si\u0119 w wyra\u017ceniach regularnych. `\\d` oznacza cyfry dziesi\u0119tne, a `\\w` litery oraz cyfry." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Je\u015bli chcemy okre\u015bli\u0107, \u017ce na danej pozycji mo\u017ce wyst\u0105pi\u0107 jeden spo\u015br\u00f3d kilku znak\u00f3w mo\u017cemy skorzysta\u0107 z w\u0142asnych klasy znak\u00f3w. Mo\u017cemy poda\u0107 bezpo\u015brednio wszystkie znaki, kt\u00f3re mog\u0105 by\u0107 dopasowane na danej pozycji:\n", "```ruby\n", "\"Ala\" =~ /[AO]la/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"Ola\" =~ /[AO]la/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"Jola\" =~ /[AO]la/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 23 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mo\u017cemy r\u00f3wnie\u017c poda\u0107 zakres liter b\u0105d\u017a cyfr. Nale\u017cy jednak pami\u0119ta\u0107, \u017ce zakresy te nie obejmuj\u0105 liter z polskimi znakami diakrytycznymi:\n", "```ruby\n", "\"Ala\" =~ /[A-Z]la/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 28 }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"\u00d3la\" =~ /[A-Z]la/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 25 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Najcz\u0119\u015bciej wykorzystywane klasy znak\u00f3w\n", "\n", "| Symbol | Znaczenie |\n", "|--------|-----------|\n", "| . | dowolny znak |\n", "| \\d | cyfra dziesi\u0119tna |\n", "| \\D | co\u015b innego ni\u017c cyfra dziesi\u0119tna |\n", "| \\s | bia\u0142e spacje |\n", "| \\S | co\u015b innego ni\u017c bia\u0142e spacje |\n", "| \\w | litery i cyfry alfabetu \u0142aci\u0144skiego |\n", "| \\W | co\u015b innego ni\u017c litery i cyfry alfabetu \u0142aci\u0144skiego |\n", "| \\p{L} | litery r\u00f3\u017cnych alfabet\u00f3w |\n", "| \\p{Lu} | du\u017ce litery r\u00f3\u017cnych alfabet\u00f3w |\n", "| \\p{Ll} | ma\u0142e litery r\u00f3\u017cnych alfabet\u00f3w |" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Zadanie 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Napisz wyra\u017cenie, kt\u00f3re dopasowuje si\u0119 do napis\u00f3w rozpoczynaj\u0105cych si\u0119 wielk\u0105 liter\u0105. Uwzgl\u0119dnij napisy takie jak: _\u0141\u00f3d\u017a_ oraz _\u017baneta_." ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Krotno\u015b\u0107" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "W wyra\u017ceniach regularnych cz\u0119sto oczekujemy, \u017ce okre\u015blony znak lub grupa znak\u00f3w pojawi si\u0119 okre\u015blon\u0105 ilo\u015b\u0107 razy. \n", "Mo\u017cna wtedy powt\u00f3rzy\u0107 wyst\u0105pienia tych znak\u00f3w lub grup znak\u00f3w, jak w przypadku dopasowania kodu pocztowego\n", "```ruby\n", "\"00-700\" =~ /\\d\\d-\\d\\d\\d/\n", "```\n", "Mo\u017cna jednak zkorzysta\u0107 z mo\u017cliwo\u015bci okre\u015blenia krotno\u015bci\n", "```ruby\n", "\"00-700\" =~ /\\d{2}-\\d{3}/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Krotno\u015b\u0107 mo\u017ce by\u0107 okre\u015blona \"sztywno\", b\u0105d\u017a mo\u017ce obejmowa\u0107 zakres:\n", "```ruby\n", "\"aaa\" =~ /a{2,4}/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"aaaaa\" =~ /a{2,4}/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cz\u0119sto oczekujemy, \u017ce okre\u015blone elementy wyst\u0105pi\u0105 zero albo wi\u0119cej razy. Wykorzystujemy wtedy gwiazdk\u0119\n", "```ruby\n", "\"aabbbcc\" =~ /ab*c/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"aacc\" =~ /ab*c/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podobnie dzia\u0142aj\u0105 operatory `+` oraz `?`. Pierwszy wymaga jednak, aby dany znak wyst\u0105pi\u0142 co najmniej jeden raz:\n", "```ruby\n", "\"aabbbcc\" =~ /ab+c/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"aacc\" =~ /ab+c/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Natomiast `?` oznacza, \u017ce element jest opcjonalny, tzn. mo\u017ce wyst\u0105pi\u0107 0 lub 1 raz\n", "```ruby\n", "\"-5\" =~ /-?\\d+/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"123\" =~ /-?\\d+/\n", "```" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Zadanie 4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Napisz wyra\u017cenie, kt\u00f3re dopasuje si\u0119 do kodu pocztowego i nazw miast wyst\u0119puj\u0105cych w Polsce. Uwzgl\u0119dnij fakt, \u017ce nazwa miasta powinna zaczyna\u0107 si\u0119 wielk\u0105 liter\u0105. Przetestuj dzia\u0142anie wyra\u017cenia na nast\u0119puj\u0105cych danych testowych:\n", "* 00-700 Warszawa\n", "* 44-196 Knur\u00f3w\n", "* 30-383 krak\u00f3w (nie powinno zosta\u0107 dopasowane)\n", "* 43-300 Bielsko-Bia\u0142a\n", "* 91-474 \u0141\u00f3D\u017a (nie powinno zosta\u0107 dopasowane)\n", "* 11-11 Polska-Japonia (nie powinno zosta\u0107 dopasowane)" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Kotwice" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ostatnim wa\u017cnym elementem pojawiaj\u0105cym si\u0119 w wyra\u017ceniach regularnych s\u0105 kotiwce - czyli takie miejsca w napisie, kt\u00f3re nie odpowiadaj\u0105 konkretnemu znakowi, lecz pewnej granicy - np. granicy pomi\u0119dzy s\u0142owem a bia\u0142\u0105 spacj\u0105. \n", "Do najcz\u0119\u015bciej stosowanych kotwic nale\u017c\u0105\n", "\n", "| Symbol | Znaczenie |\n", "|---------|-----------|\n", "| ^ | Pocz\u0105tek wiersza |\n", "| $ | Koniec wiersza |\n", "| \\A | Pocz\u0105tek napisu |\n", "| \\z | Koniec napisu |\n", "| \\b | granica s\u0142owa |\n", "\n", "Przyk\u0142adowo je\u015bli chcemy dopasowa\u0107 \"Ala\", ale tylko wtedy gdy pojawia si\u0119 na pocz\u0105tku wiersza, musimy u\u017cy\u0107 kotwicy:\n", "```ruby\n", "\"Ala ma kota\" =~ /^Ala/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"To kot, a to Ala\" =~ /^Ala/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Kotwica `\\b` przydaje si\u0119 je\u015bli chcemy np. podzieli\u0107 napis wzgl\u0119dem granic s\u0142\u00f3w:\n", "```ruby\n", "\"Ala ma kota\".split(/\\b/)\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 30 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dzi\u0119ki niej mo\u017cemy r\u00f3wnie\u017c upewni\u0107 si\u0119, \u017ce dopasowujemy konkretne s\u0142owo, a nie liter\u0119 wewn\u0105trz s\u0142owa. Por\u00f3wnaj\n", "```ruby\n", "\"Ania i Kasia\" =~ /i/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```ruby\n", "\"Ania i Kasia\" =~ /\\bi\\b/\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Zadanie 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Napisz algorytm, kt\u00f3re z adresu URL wyodr\u0119bnia:\n", "* protok\u00f3\u0142\n", "* adres hosta\n", "* numer portu (opcjonalny)\n", "* \u015bcie\u017ck\u0119\n", "* zapytanie\n", "* fragment dokumentu\n", "\n", "Przyk\u0142adowy adres do testowania:\n", "http://www.wp.pl:8080/aktualnosci/krakow/1112.html?id=5#tresc\n", "\n", "Powinni\u015bmy otrzyma\u0107 nast\u0119puj\u0105cy wynik ko\u0144cowy:\n", "```\n", "protok\u00f3\u0142: http\n", "host: www.wp.pl\n", "port: 8080\n", "\u015bcie\u017cka: /aktualnosci/krakow/1112.html\n", "zapytanie: id=5\n", "fragment: tresc\n", "```" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }