{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Seminar Problemorientierte Programmierung\n",
    "\n",
    "\n",
    "## Exkurs: Was mir an Python gefällt\n",
    "\n",
    "In dieser Rubrik, die immer am Anfang eines Kapitels steht, möchte ich Ihnen zeigen, wofür ich Python nutze und warum ich es mag. Sie werden vielleicht noch nicht verstehen, was ich genau mache, aber Sie sehen damit schon einmal die Möglichkeiten von Python und können später darauf zurückgreifen. Da dies auch ein Exkurs ist, können Sie diese Rubrik gerne auch erst einmal überspringen.\n",
    "\n",
    "In einer Datei alle E-Mail-Adressen extrahieren geht recht einfach:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import re\n",
    "\n",
    "def find_in_file(pattern, file):\n",
    "    reg_pattern = re.compile(pattern)\n",
    "    for line in file:\n",
    "        for found in reg_pattern.findall(line):\n",
    "            print(found[0])\n",
    "\n",
    "find_in_file(r\"([a-zA-Z0-9-!#$%&'*+-/=?^_`{|}~]+@([A-Za-z0-9-]+\\.)+[a-zA-Z]{2,})\", open(\"test.txt\", \"rt\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 Extra: Reguläre Ausdrücke\n",
    "\n",
    "Dieses Kapitel taucht nicht im Python-Kurs auf und wird separat gepflegt.\n",
    "\n",
    "In der Praxis können wir reguläre Ausdrücke nutzen, um in Texten zu suchen und Muster zu entdecken. Python bietet uns im `re`-Modul (re = Regular Expression = Regulärer Ausdruck) viele Funktionen an, um mit regulären Ausdrücken zu arbeiten. \n",
    "\n",
    "Es gibt dabei zwei \"Dimensionen\" an denen wir uns \"entlanghangeln\" müssen: die Funktionen, die vom `re`-Modul bereitgestellt werden und die regulären Ausdrücke selber, die komplex werden können. Wir beginnen zunächst mit nur einer Funktion und werden Stück für Stück komplexere Ausdrücke kennenlernen. Dann schauen wir uns weitere Funktionen an. \n",
    "\n",
    "###  3.1 Einfache Suche\n",
    "\n",
    "Wir können mit der Funktion `findall` alle Teilzeichenketten in einer Zeichenkette finden, die auf ein gegebenes Muster (in Form eines regulären Ausdrucks) passen. Die Funktion erwartet zwei Argumente: einen regulären Ausdruck und die Zeichenkette, die durchsucht werden soll: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import re\n",
    "re.findall(r'f[a-z]*', 'which foot or hand fell fastest')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Das Beispiel erklärt:\n",
    "1. In der ersten Zeile sehen wir, dass das `re`-Modul importiert wird. Das muss einmal am Anfang unseres Programms passieren. Hier im Jupyter-Notebook reicht es, wenn das Modul in einem Block importiert wird - sobald der Block ausgeführt wurde, kann es dann in allen folgenden Blöcken verwendet werden.\n",
    "2. In der nächsten Zeile sehen wir, wie mittels der Punkt-Notation die `findall`-Funktion im `re`-Modul aufgerufen wird.\n",
    "3. Der Funktion werden zwei Argumente übergeben: `r'f[a-z]*'` und `'which foot or hand fell fastest'`.\n",
    "4. Das erste Argument ist ein regulärer Ausdruck. Reguläre Ausdrücke werden in Hochkommata `''` eingeschlossen und beginnen mit einem `r`. \n",
    "5. D.h., der eigentliche reguläre Ausdruck lautet `f[a-z]*`. Dieser Ausdruck beschreibt Zeichenketten, die mit einem `f` beginnen und von beliebig (auch 0!) vielen (`*`) Kleinbuchstaben (`[a-z]`) gefolgt werden. \n",
    "6. Der Ausdruck `[a-z]` in eckigen Klammern beschreibt ein Zeichen, welches die Werte von `a` bis `z` haben darf. Das Symbol `*` dahinter besagt, dass das vor `*` beschriebene Zeichen beliebig oft wiederholt werden darf. Die Kombination `[a-z]*` beschreibt also beliebig viele Zeichen zwischen `a` und `z`. \n",
    "7. Das zweite Argument (`'which foot or hand fell fastest'`) ist die Zeichenkette, in der wir nach Teilzeichenketten suchen, die auf den übergebenen regulären Ausdruck passen.\n",
    "\n",
    "Das Ergebnis des Aufrufs von `findall` ist eine Liste der Teilzeichenketten, die auf das Muster passen - in unserem Beispiel sind das die Zeichenketten `foot`, `fell` und `fastest`. \n",
    "\n",
    "Probieren Sie es hier selber aus:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "regaus = r'f[a-z]*'\n",
    "text = input(\"Geben Sie eine Zeichenkette zum Testen ein:\")\n",
    "ergebnis = re.findall(regaus, text)\n",
    "if ergebnis:\n",
    "    print(\"Es wurden folgende Teilzeichenketten erkannt:\", ergebnis)\n",
    "else:\n",
    "    print(\"Leider wurde nichts erkannt, probieren Sie es noch einmal.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ändern Sie den regulären Ausdruck im folgenden Beispiel, so dass alle Wörter, die mit einem `b` beginnen ausgegeben werden: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "re.findall(r'b', 'Wir bauten und bohrten bis das Haus fertig war.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Die Ausgabe sollte so aussehen:\n",
    "```\n",
    "['bauten', 'bohrten', 'bis']\n",
    "```\n",
    "Ändern Sie den regulären Ausdruck, so dass jetzt nur Wörter ausgegeben werden, die mit einem `b` beginnen und mit einem `n` enden. Die Ausgabe sollte dann so aussehen:\n",
    "```\n",
    "['bauten', 'bohrten']\n",
    "```\n",
    "\n",
    "Welche Probleme sind bei Ihren Versuchen aufgetreten?\n",
    "- \n",
    "- \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 Schritt für Schritt: ein beliebiges Zeichen\n",
    "\n",
    "Der Punkt `.` steht für ein beliebiges Zeichen: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "re.findall(r'a.', \"Am Anfang aßen wir alle Manna und Kartoffeln\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Im Satz `Am Anfang aßen wir alle Kartoffeln.` gibt es genau sechs Vorkommen von einem kleinen `a` mit einem Zeichen dahinter. Wie wir sehen, wird auch das `a` am Ende von `Manna`, welches von einem Leerzeichen gefolgt ist, erkannt. Das liegt daran, dass der Punkt für wirklich jedes Zeichen (auch das Leerzeichen) steht. Die zwei Zeichenketten `Am` und `An` werden nicht erkannt, da sie ein großes `A` enthalten, wir aber nach einem kleinen gesucht haben."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sie kennen jetzt eine Funktion, um reguläre Ausdrücke in Python anzuwenden und damit Texte zu durchsuchen. Weitere Funktionen ermöglichen die Extraktion und das Ersetzen von Teilzeichenketten in Texten. Bevor wir diese Funktionen kennenlernen, ist es praktisch, mit regulären Ausdrücken vertraut zu werden. Eine sehr gute interaktive Übungsseite dazu finden Sie hier: https://regexone.com/lesson/introduction_abcs. Arbeiten Sie diese Seite gemeinsam Schritt für Schritt durch. Schrecken Sie nicht vor dem englischen Text zurück - ich helfe Ihnen bei Fragen gerne weiter.\n",
    "\n",
    "Es gibt noch viele andere gute Tutorials zu regulären Ausdrücken, z.B. [hier](https://ryanstutorials.net/regular-expressions-tutorial/) oder [hier](https://www.python-kurs.eu/re.php). Sie können auch eine dieser Anleitungen durcharbeiten, wenn Sie damit besser zurechtkommen."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![Speichern](https://amor.cms.hu-berlin.de/~jaeschkr/teaching/spp/floppy.png) Speichern Sie dieses Notebook, so dass Ihre Änderungen nicht verlorengehen (nicht auf einem Pool-Rechner). Klicken Sie dazu oben links auf das Disketten-Icon und nutzen Sie beispielsweise einen USB-Stick, E-Mail, Google Drive, Dropbox oder Ihre [HU-Box](https://box.hu-berlin.de/).  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![Smiley](https://upload.wikimedia.org/wikipedia/commons/a/a7/Emblem-fun.svg)\n",
    "\n",
    "Herzlichen Glückwunsch! Sie haben das 3. Kapitel geschafft. Weiter geht es in [4: Fallstudie: Schnittstellenentwurf](seminar04.ipynb)."
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}