automata-labs/lab-02.ipynb

603 lines
14 KiB
Plaintext
Raw Normal View History

2024-11-24 21:18:17 +01:00
{
"cells": [
{
"cell_type": "markdown",
"source": [
"# Języki formalne i złożoność obliczeniowa\n",
"## Część 1: Wprowadzenie do biblioteki re\n"
],
"metadata": {
"collapsed": false
},
"id": "f5376d249e31d5aa"
},
{
"cell_type": "markdown",
"source": [
"Wyrażenia regularne będziemy robić na podstawie języka python3. Dokumentacja: https://docs.python.org/3.11/library/re.html\n",
"\n",
"Użyteczna strona do testowania wyrażeń regularnych: https://regex101.com/\n"
],
"metadata": {
"collapsed": false
},
"id": "ce091d4ec144df32"
},
{
"cell_type": "markdown",
"source": [
"# Podstawowe funkcje"
],
"metadata": {
"collapsed": false
},
"id": "35428280eb1f704"
},
{
"cell_type": "markdown",
"source": [
"## Match\n",
"match - zwraca dopasowanie od początku stringa"
],
"metadata": {
"collapsed": false
},
"id": "9674be284007455d"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"import re\n",
"wynik = re.match(r'Ala', 'Ala ma kota. Kot ma Alę.')\n",
"print(wynik)\n",
"print(f\"Dopasowano: '{wynik.group()}', początek: {wynik.start()}, koniec: {wynik.end()}\")\n"
],
"metadata": {
"collapsed": false
},
"id": "fa7637b60ae679b5"
},
{
"cell_type": "markdown",
"source": [
"## Search\n",
"search - zwraca pierwsze dopasowanie w napisie\n"
],
"metadata": {
"collapsed": false
},
"id": "626c591ab52a086"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"# search\n",
"wynik = re.search(r'ni', 'Może nie najtaniej, ale jako tako.')\n",
"\n",
"if wynik:\n",
" print(f\"Dopasowano: '{wynik.group()}', początek: {wynik.start()}, koniec: {wynik.end()}\")\n",
"else:\n",
" print('Nie znaleziono szukanego ciągu znaków.')"
],
"metadata": {
"collapsed": false
},
"id": "4f5d7077a85b7108"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"tekst = \"Kto zakłóca ciszę nocną musi ponieść karę: 100 batów!\"\n",
"\n",
"wzorzec = re.compile('ci')\n",
"\n",
"wynik = wzorzec.search(tekst)\n",
"\n",
"if wynik:\n",
" print(f\"Dopasowano: '{wynik.group()}', początek: {wynik.start()}, koniec: {wynik.end()}\")\n",
"else:\n",
" print('Nie znaleziono szukanego ciągu znaków.')"
],
"metadata": {
"collapsed": false
},
"id": "b9da286f8d6936fb"
},
{
"cell_type": "markdown",
"source": [
"## findall\n",
"findall - zwraca listę wszystkich dopasowań\n"
],
"metadata": {
"collapsed": false
},
"id": "600b87dd6af48c04"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"# findall\n",
"wzorzec = re.compile('o')\n",
"\n",
"wynik = wzorzec.findall(tekst)\n",
"\n",
"if len(wynik) > 0:\n",
" print(type(wynik))\n",
" print(f'Dopasowano: {wynik}')\n",
"else:\n",
" print(f'{wynik} Nie znaleziono szukanego ciągu znaków.')"
],
"metadata": {
"collapsed": false
},
"id": "37a93d9d61c6178d"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"wzorzec = re.compile('o')\n",
"\n",
"wynik = wzorzec.finditer(tekst)\n",
"for w in wynik:\n",
" print(type(w))\n",
" print(f'Dopasowano: \"{w.group()}\", początek: {w.start()}, koniec: {w.end()}')"
],
"metadata": {
"collapsed": false
},
"id": "3232906632de2fe1"
},
{
"cell_type": "markdown",
"source": [
"*Uwaga*: pobierając z iteratora elementy, usuwamy je, nie można zatem ponownie się do nich odwołać."
],
"metadata": {
"collapsed": false
},
"id": "62e8a0370ee58827"
},
{
"cell_type": "markdown",
"source": [
"## Użycie przedrostka 'r' w wyrażeniach regularnych w Pythonie\n",
"\n",
"W Pythonie przedrostek `r` przed łańcuchem znaków oznacza \"surowy\" łańcuch znaków (ang. *raw string*). Dlaczego jest to przydatne w kontekście wyrażeń regularnych?\n",
"\n",
"Wyrażenia regularne często używają znaków specjalnych, takich jak `\\d`, `\\w`, `\\b` itp. W standardowych łańcuchach znaków w Pythonie, znaki te mają specjalne znaczenie. Na przykład, `\\t` oznacza tabulację, a `\\n` oznacza nową linię.\n",
"\n",
"Jeśli chcemy użyć takiego wyrażenia regularnego w Pythonie, musielibyśmy podwajać znaki ukośnika, aby uniknąć konfliktu z wbudowanymi sekwencjami ucieczki w łańcuchach znaków, np. `\\\\d`, `\\\\w`."
],
"metadata": {
"collapsed": false
},
"id": "6342ff85cd5fc35a"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"# Bez użycia surowego łańcucha znaków\n",
"result1 = re.findall(\"\\\\d+\", \"123 abc 456\")\n",
"print(result1)\n",
"\n",
"# Używając surowego łańcucha znaków\n",
"result2 = re.findall(r\"\\d+\", \"123 abc 456\")\n",
"print(result2)\n"
],
"metadata": {
"collapsed": false
},
"id": "b09fa3103ec18719"
},
{
"cell_type": "markdown",
"source": [
"## sub\n",
"Kolejną użyteczną metodą jest sub(), która pozwala na zmianę wzorca na inny ciąg znaków:"
],
"metadata": {
"collapsed": false
},
"id": "e9e3f41e90bbd746"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"wzorzec = re.compile(r'ni')\n",
"\n",
"zmieniony = wzorzec.sub('Ni!', tekst)\n",
"print(zmieniony)"
],
"metadata": {
"collapsed": false
},
"id": "af633211d7faca67"
},
{
"cell_type": "markdown",
"source": [
"## split\n",
"split - dzieli napis na podstawie wzorca"
],
"metadata": {
"collapsed": false
},
"id": "ea9205aa03ed7476"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"wzorzec = re.compile(r' ')\n",
"\n",
"wynik = wzorzec.split(tekst)\n",
"print(f'Uzyskano {len(wynik)} wyniki/ów.')\n",
"for w in wynik:\n",
" print(w)"
],
"metadata": {
"collapsed": false
},
"id": "71dc3b254a93f31c"
},
{
"cell_type": "markdown",
"source": [
"# Metaznaki\n",
"[] - zbiór znaków\n",
"\n",
". - jakikolwiek znak\n",
"\n",
"^ - początek napisu\n",
"\n",
"$ - koniec napisu\n",
"\n",
"? - znak występuje lub nie występuje\n",
"\n",
"\\* - zero albo więcej pojawień się\n",
"\n",
"\\+ - jeden albo więcej pojawień się\n",
"\n",
"{} - dokładnie tyle pojawień się\n",
"\n",
"| - lub\n",
"\n",
"() - grupa\n",
"\n",
"\\ - znak ucieczki\n",
"\n",
"\\d digit\n",
"\n",
"\\D nie digit\n",
"\n",
"\\s whitespace\n",
"\n",
"\\S niewhitespace"
],
"metadata": {
"collapsed": false
},
"id": "4b16abb6848f09ae"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"wzorzec = re.compile(r'.')\n",
"print(wzorzec.findall(tekst))"
],
"metadata": {
"collapsed": false
},
"id": "ac6669cac4f52d27"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"# jeden lub wiecej / zero lub wiecej\n",
"\n",
"tekst = \"BCAAABGTAABBBCCTTSAGG4324242\"\n",
"print(f'Łańcuch: {tekst}')\n",
"wzorzec = re.compile(r'X+')\n",
"print(f'Jeden lub więcej X: {wzorzec.findall(tekst)}')\n",
"wzorzec = re.compile(r'X*')\n",
"print(f'Zero lub więcej X: {wzorzec.findall(tekst)}')"
],
"metadata": {
"collapsed": false
},
"id": "634e4b66a5081f97"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"# zero lub jeden\n",
"\n",
"print(f'Łańcuch: {tekst}')\n",
"wzorzec = re.compile(r'.?')\n",
"print(wzorzec.findall(tekst))\n",
"wzorzec = re.compile(r'.?T')\n",
"print(wzorzec.findall(tekst))"
],
"metadata": {
"collapsed": false
},
"id": "44195e00a81b23fb"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"print(f'Łańcuch: {tekst}')\n",
"wzorzec = re.compile(r'A+')\n",
"print(f'Dopasowanie zachłanne: {wzorzec.findall(tekst)}')\n",
"wzorzec = re.compile(r'A+?')\n",
"print(f'Dopasowanie leniwe: {wzorzec.findall(tekst)}')"
],
"metadata": {
"collapsed": false
},
"id": "ea861a33e942d42a"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"print(f'Łańcuch: {tekst}')\n",
"\n",
"# dokladnie 3 dopasowania\n",
"wzorzec = re.compile(r'A{3}')\n",
"print(f'{wzorzec.findall(tekst)}')\n",
"\n",
"# pomiedzy 2 i 3 dopasowania\n",
"wzorzec = re.compile(r'A{2,3}')\n",
"print(f'{wzorzec.findall(tekst)}')\n",
"\n",
"# 2 lub wiecej dopasowan\n",
"wzorzec = re.compile(r'A{2,}')\n",
"print(f'{wzorzec.findall(tekst)}')\n",
"\n",
"# 3 lub mniej dopasowan\n",
"wzorzec = re.compile(r'A{,3}')\n",
"print(f'{wzorzec.findall(tekst)}')"
],
"metadata": {
"collapsed": false
},
"id": "751272b81731af36"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"# poczatek lub koniec lancucha\n",
"\n",
"tekst = \"Ale pięknie pachnie! Maciek, co gotujesz?\"\n",
"\n",
"# poczatek lancucha\n",
"wzorzec = re.compile(r'^Ale')\n",
"print(f'{wzorzec.findall(tekst)}')\n",
"\n",
"# poczatek lancucha\n",
"wzorzec = re.compile(r'^ale')\n",
"print(f'{wzorzec.findall(tekst)}')\n",
"\n",
"# koniec lancucha\n",
"wzorzec = re.compile(r'Ale$')\n",
"print(f'{wzorzec.findall(tekst)}')\n",
"\n",
"# koniec lancucha + znak ucieczki\n",
"wzorzec = re.compile(r'gotujesz\\?$')\n",
"print(f'{wzorzec.findall(tekst)}')"
],
"metadata": {
"collapsed": false
},
"id": "97bcd3ff7cc3913"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"# grupy znakow\n",
"wzorzec = re.compile(r'[A-Z]')\n",
"print(f'Duże litery: {wzorzec.findall(tekst)}')\n",
"\n",
"wzorzec = re.compile(r'[a-z]')\n",
"print(f'Małe litery: {wzorzec.findall(tekst)}')\n",
"\n",
"wzorzec = re.compile(r'[A-z]')\n",
"print(f'Małe i duże litery: {wzorzec.findall(tekst)}')\n",
"\n",
"wzorzec = re.compile(r'[aeiou]')\n",
"print(f'Samogłoski: {wzorzec.findall(tekst)}')"
],
"metadata": {
"collapsed": false
},
"id": "ee099e6e1e5e2f80"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"# wzorzec(?=X) - dopasowanie, jeśli po nim występuje X\n",
"\n",
"tekst = \"ACABADAHSAIIIQIIINSAODIANSAAGAGAGGGGPAAG\"\n",
"\n",
"print(f'Łańcuch: {tekst}')\n",
"wzorzec = re.compile(r'G+(?=A)')\n",
"print(f'{wzorzec.findall(tekst)}')"
],
"metadata": {
"collapsed": false
},
"id": "dd6351952639ef42"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"tekst = \"Ale się zrobiła świąteczna atmosfera.\"\n",
"wzorzec = re.compile(r'Ale|świąteczna|zrobiła')\n",
"print(f'{wzorzec.findall(tekst)}')"
],
"metadata": {
"collapsed": false
},
"id": "c7f3e1b9d16c91db"
},
{
"cell_type": "markdown",
"source": [
"## Znaki specjalne\n",
"\n",
"\\s\t- biały znak\n",
"\n",
"\\S\t- nie-biały znak\n",
"\n",
"\\d\t- cyfra\n",
"\n",
"\\D\t- nie-cyfra\n",
"\n",
"\\w\t- znaki alfanumeryczne (litery i cyfry) oraz\n",
" \n",
"\\W\t- znaki nie-alfanumeryczne i nie\n",
" \n",
"\\b\t- początek lub koniec ,,słowa\n",
" \n",
"\\B\t- nie początek lub koniec ,,słowa''\n",
"\n",
"[a-z]\t- małe litery\n",
"\n",
"[A-Z]\t- wielkie litery\n",
"\n",
"[0-9]\t- cyfry\n"
],
"metadata": {
"collapsed": false
},
"id": "c1a7435b7887f5c2"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"wzorzec = re.compile(r'\\w+')\n",
"print(f'Wyrazy: {wzorzec.findall(tekst)}')\n"
],
"metadata": {
"collapsed": false
},
"id": "3b1b1f147233455d"
},
{
"cell_type": "markdown",
"source": [
"## Część II: Zadania praktyczne\n",
"\n",
"### Zadanie 1: Wyszukiwanie numerów telefonu\n",
"\n",
"Napisz wyrażenie regularne, które znajdzie wszystkie numery telefonu w tekście. Zakładamy, że numer telefonu ma format `xxx-xxx-xxx` lub `xxx xxx xxx`.\n"
],
"metadata": {
"collapsed": false
},
"id": "e0670d19927add2b"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"tekst = \"\"\"\n",
"Jan: 123-456-789\n",
"Anna: 987 654 321\n",
"Karol: 456-789-123\n",
"Zbyszek: 53252525342252\n",
"Tytus: aaaa666432\n",
"\"\"\"\n",
"\n",
"wzorzec = re.compile(r\"\")\n",
"print(f'Numery: {wzorzec.findall(tekst)}')"
],
"metadata": {
"collapsed": false
},
"id": "aecbbf61477429ac"
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"tekst = \"\"\"\n",
"jan.kowalski@gmail.com\n",
"anna.zielinska@amu.edu.pl\n",
"karol.nowak@interia.pl\n",
"hello world\n",
"@test.pl\n",
"x@x\n",
"fff22@gmail.com\n",
"\"\"\"\n",
"\n",
"wzorzec = re.compile(r\"\")\n",
"print(f'Adresy: {wzorzec.findall(tekst)}')"
],
"metadata": {
"collapsed": false
},
"id": "1dcf9585d7b78073"
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}