====== Regular Expressions ======
Beschreibung von Text-Mustern. Zum Suchen, Extrahieren und Ersetzen von Text.
Gibt es in (fast) allen Programmiersprachen und jedem besseren Text-Editor (z.B. Notepad++, VisualCode, vim, etc.)
Je nach Implementation gibt es kleine Unterschiede zwischen Programmiersprachen oder Text-Editoren.
===== Wichtigste Spezialzeichen =====
Wenn nicht speziell, steht ein Zeichen für sich selbst in einer regular Expression. Z.B. matcht /hallo/ nur genau "hallo"
* ''.'' steht für genau ein beliebiges Zeichen (ausser Zeilenumbruch)
* ''\.'' steht für einen Punkt
* ''[abc246]'' steht für genau ein beliebiges Zeichen in der Klammer
* ''[5-9e-k]'' steht für genau ein Zeichen '5' bis '9' oder 'e' bis 'k'
* ''\d'' Digit, Abkürzung für ''[0-9]''.
* ''\['' steht für die öffnende Klammer
* ''^'' Start der Zeile (oder String)
* ''$'' Ende der Zeile (oder String)
Quantoren:
* ''*'' beliebig viele der Expression davor (auch Null), **greedy**, d.h. match't so viel wie irgend möglich
* ''+'' ein oder mehrere der Expression davor, **greedy**
* ''?'' Null oder eins, **greedy**
* ''{7}'' genau 7
* ''{4,7}'' zwischen 4 und 7, **greedy**
* ''*?'' beliebig viele, aber **lazy** (d.h. match't so wenig wie möglich). Ebenso ''??'', ''+?'' und ''{4,7}?''.
Gruppen:
* ''(''expr'')'' «speichert» den Match zur späteren Verwendung mit ''\1'' oder ''$1'', je nach Engine. Es wird nach öffnender Klammer nummeriert.
Alternativen:
* ''|'' Die Expression davor, oder jene danach.
===== Ausprobieren =====
* https://regex101.com/ Verwenden Sie Python. Die Dokumentation von Python RegEx: https://docs.python.org/3/library/re.html
* http://regextutorials.com/
* https://regexcrossword.com/
* https://alf.nu/RegexGolf (Yay!)
* https://regexone.com/
* https://regex.sketchengine.eu/basic-exercises.html
==== Aufgabe: Links extrahieren ====
* Extrahieren Sie alle Links von folgendem Code-Schnipsel:
./68ac1106/spaceadventure.html
* Vervollständigen Sie obige Links mit der vollständigen Adresse: https://ofi.tech-lab.ch/2022/EF05a/
* Im angezeigten Text soll die Pfadangabe und das .html verschwinden (also nur noch wordle anstatt ./05c7c22f/wordle.html)
./0475c543/mouseEffect.html
./76163dbd/Taschenrechner.html
./4b29d86a/index.html
./05c7c22f/wordle.html
./4d4f79fa/index.html
./2750fa3e/index.html
./projects.html
search for
'(.*?)'
search for
'.\/(.*?)'
replace by
'https://ofi.tech-lab.ch/2022/EF05a/$1'
search for
>\.\/.*?\/(.*?)\.html<
replace by
>$1<
scp ef:python/logs/xmaslights-2023-11-30T164809.401678.log .
Mögliche Fragen:
* Welches Programm wurde besonders oft ausgewählt?
* Um welche Uhrzeiten hat der Bewegungsmelder etwas wahrgenommen? Plotten Sie das auch schön.
import re
fn = "xmaslights-2023-11-30T164809.401678.log"
with open(fn, "r") as f:
lines = f.readlines()
pattern = re.compile("since motion: (\d+\.\d+)")
#pattern = re.compile("text=")
for line in lines:
res = pattern.search(line)
if res:
#print(line)
print(res.group(1))
==== Realworld-Aufgabe: Daten aus einer Nesa-Seite extrahieren ====
Hier finden Sie einen Screenshot und den zughörigen HTML-Code: {{lehrkraefte:blc:informatik:efi-2023:raumplanh21.zip}}.
Schreiben Sie ein Python-Programm mit regular Expressions, das den Raumplan extrahiert.
=== Warum das Blödsinn ist ===
Gegen eine UI zu programmieren, ist ok für den Einmalgebrauch. Es ist aber nicht nachhaltig, weil die UI jederzeit ändern kann (und wird!).
Auch haben wir HTML-Code vorliegen. Dieser ist bereits strukturiert und auch danach durchsuchbar. Z.B. kann man die Sache in JavaScript «relativ» einfach erledigen (In den Entwickler Tools des Webbrowsers (F12)):
Array.from(document.querySelectorAll('.stpt_event_body')).map(e=>e.getAttribute('title'))
Liefert ein Array mit den gewünschten Einträgen.
==== Weitere Übungen ====
Mit einem [[https://fginfo.ksbg.ch/dokuwiki/doku.php?id=lehrkraefte:blc:informatik:ffprg1-2022:wordle:start#wortliste|Crawler in Python]] habe ich deutsche Wortlisten erstellt: {{kurse:ef05a-2021:wortliste05.txt}}.
Diese Wortliste soll z.B. für ein Wordle-Spiel gebraucht werden. Dazu sind allerdings noch einige Aufräumarbeiten nötig:
* Extrahieren Sie erst die Zeilen, deren Wörter mindestens 100 mal gefunden wurden.
* Hinweis: Das könnte auch auf der Kommandozeile mittels ''grep -e'' //regexp// ''wortliste05.txt'' geschehen.
* Entfernen Sie alle Zahlen (und den Leerschlag)
* Hinweis: das könnte auch auf der Kommandozeile mittels ''cut -f1 -d" "'' erreicht werden.
Dann wollen wir mal «spezielle» Wörter suchen:
* Suchen Sie alle Wörter, die einen Doppelbuchstaben (zwei gleich hintereinander) haben.
* Suchen Sie alle Wörter, in denen ein Buchstabe zwei mal vorkommt.
* Suchen Sie alle Wörter, in denen ein Buchstabe drei mal vorkommt.
Auf https://sourceforge.net/projects/germandict/ gibt es eine Wortliste mit 1.2 Millionen Wörten, die in deutschen Texten vorkommen können. Extrahieren Sie daraus:
* Evtl. ß durch ss ersetzen.
* Evtl. ä, ö, ü durch ae, oe, ue ersetzen.
* Wörter die aus genau 5 Buchstaben A-Z und a-z bestehen
* Nur der erste Buchstaben darf gross sein, alle anderen müssen klein sein.
* Das Wort muss mindestens einen Vokal enthalten.
* Liste sortieren, doppelte Wörter entfernen.
* Danach bleiben {{kurse:ef05a-2021:huge5.txt|6308 Wörter.}}
cat utf8.txt | sed -e s/ß/ss/g | sed -e s/ä/ae/g | sed -e s/ö/oe/g | sed -e s/ü/ue/g | grep -E '^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvxzy][abcdefghijklmnopqrstuvxzy]{4}$' | grep -E '[AEIOUaeiou]' | tr 'a-z' 'A-Z' | sort | uniq | wc
[^OENICHKAGL\n]{3}LT
^NRA[^BOTULKGZA]S|^[^BOTULKGZA]RANS
^S[^INDZGERPT]O[^INDZGERPT]{2}
^NE[^KATJOLSHR]R[^KATJOLSHRN]|^[^KATJOLSHR]ENR[^KATJOLSHRN]
==== Alternativen für HTML, JSON, XML und allg. maschinenlesabare Formate ====
Um Daten aus HTML, JSON oder XML nachhaltig zu extrahieren/manipulieren, ist es ratsam, Werkzeuge zu verwenden, die das entsprechende Format verstehen, z.B. für
* HTML: direkt mit JavaScript und z.B. [[https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector|document.querySelector]] arbeiten.
* JSON: Daten parsen (in irgendeiner Programmiersprache) und direkt dort manipulieren.
* XML: dafür gibt es ebenfalls Parser
Das Problem mit «selbstgestrickten» regular Expressions ist, dass diese halt schnell an ihre Grenzen stossen und zu wenige oder zu viele Resultate liefern.
===== Weiterführende Links =====
* Advanced stuff: http://rexegg.com/regex-best-trick.html