KI-Werkzeuge in der Softwareentwicklung

In der Softwareentwicklung existierten schon immer Werkzeuge und Vereinfachungen wie Autocompletion oder Syntax-Highlighting, die den Entwicklungsprozess effizienter und weniger fehleranfällig machen sollten. Diese Werkzeuge haben es Entwicklern ermöglicht, sich stärker auf die Logik und Funktionalität ihres Quellcodes zu konzentrieren, anstatt sich mit den Details der Syntax oder der Strukturierung von Quellcode herumzuschlagen.

In den vergangenen Jahren hat sich die Landschaft der Softwareentwicklung weiterentwickelt und neue Technologien und Methoden haben Einzug gehalten. Beispielsweise haben Versionskontrollsysteme wie Git die Zusammenarbeit in Teams wesentlich verbessert und Continuous-Integration-/Continuous-Deployment-Pipelines ermöglichen es, Änderungen effizienter in Produktionsumgebungen zu bringen.

KI-Werkzeuge sollen die Entwicklungsarbeit vereinfachen

Aktuell finden immer mehr Werkzeuge, die mit maschinellem Lernen oder großen Sprachmodellen (Large Language Models) arbeiten, ihren Weg in die Praxis. Assistenten wie GitHub Copilot oder Tabnine nutzen hierbei große Mengen an Trainingsdaten, um Entwicklern kontextbezogene Vorschläge anzubieten, die weit über einfache Autocompletion hinausgehen. So können komplexere Code-Snippets vorgeschlagen oder ganze Methoden und Funktionen auf Basis kurzer Beschreibungen generiert werden.

Im Idealfall soll dies die Produktivität erhöhen, auch wenn das letzte Wort hierbei noch nicht gesprochen ist. Doch welche Werkzeuge existieren? Im Rahmen des Artikels soll ein Blick auf spezialisiertere Lösungen zur Entwicklung abseits von ChatGPT und Co. geworfen werden.

Arten von Werkzeugen

Auf dem Markt der KI-Werkzeuge zur Softwareentwicklung existieren Werkzeuge unterschiedlicher Couleur. Neben Integrationen für eine Anzahl von IDEs, existieren Standalone-Tools und auch webbasierte Tools. Viele KI-Werkzeuge sind als Plugins oder Erweiterungen für IDEs wie Visual Studio Code oder IntelliJ IDEA verfügbar. Diese Integrationen ermöglichen es, KI-gestützte Funktionen direkt in der gewohnten Entwicklungsumgebung zu nutzen, was den Arbeitsablauf verbessert.

Einige dieser Werkzeuge bieten spezialisierte Funktionen, die auf bestimmte Aspekte der Softwareentwicklung abzielen, wie Code-Generierung, Fehlererkennung, Optimierung, Review oder Testautomatisierung.

Code-Assistenten

Einer der häufigsten neuen Werkzeug-Typen sind Code-Assistenten, welche es ermöglichen Quellcode zu generieren und diese Fähigkeit in einer Entwicklungsumgebung einzusetzen. Daneben können Fragen zum Quellcode gestellt, Dokumentationen erzeugt, oder Vorschläge für ein Refactoring erzeugt werden.

Bei diesen Code-Assistenten finden sich etliche Schwergewichte der IT, wie Amazon oder Microsoft wieder.

Amazon Q

Als Antwort auf GitHub Copilot stellte Amazon CodeWhisperer vor. Mittlerweile ist dieses Werkzeug in Amazon Q aufgegangen.

Für Entwickler dürfte das Teilprodukt Amazon Q Developer interessant sein. Für dieses sind unter anderem Integrationen für die JetBrains IDEs, VS-Code und Visual Studio verfügbar. Auch eine Version für die Kommandozeile wird geboten.

Amazon Q in einer Jetbrains IDE

Für den Assistenten wird eine AWS Builder ID benötigt. Im begrenztem Rahmen kann der Assistent, damit kostenlos ausprobiert werden.

Sinnvolle Ergebnisse liefert der Assistenz nur bei Anfragen in englischer Sprache. Interessant ist die Möglichkeit, Quelltext zu generieren, der über mehrere Dateien reicht. Hier haben andere Assistenten meist ihre Probleme und erzeugen nur Quellcode an einem Stück.

Gesteuert wird der Assistent über Befehle wie /dev mit einem darauffolgenden Prompt. Angeboten wird neben der kostenlosen Variante, ein Business Lite und ein Business Pro Abonnement.

Insgesamt fühlt sich Amazon Q als generisches KI-Werkzeug zur Entwicklung unzureichend an, allerdings könnte es anders aussehen, wenn eine engere Verzahnung mit AWS und die Nutzung eigener Geschäftsdaten gewünscht wird.

Codeium

Codeium ist ebenfalls ein Code-Assistent, welcher sich in unterschiedlichste IDEs integriert.

Codeium unterstützt eine Reihe von IDEs

Das Plugin verfügt über eine Chat-Funktionalität, welche es ermöglicht Anforderungen bzw. Prompts zu definieren. Negativ fällt auf, dass hier die aktuell genutzte Programmiersprache nicht automatisch erkannt wird, sondern explizit angegeben werden muss.

Auch das Antworten auf bereits erzeugte Nachrichten muss separat erledigt werden. Wird stattdessen direkt im Chatfenster geantwortet, wird eine neue unabhängige Konversation gestartet. Soll auf einen vorherigen Chat Bezug genommen werden, so muss der Continue this chat-Button genutzt werden.

Die Chat-Funktionalität nutzt die falsche Programmiersprache

Interessanter ist die Möglichkeit, relativ unkompliziert Unit-Tests für ausgewählte Methoden zu generieren. Hierfür wird eine Methode ausgewählt und entsprechende Testfälle werden ermittelt und anschließend in Code umgesetzt.

Codium erzeugt Testfälle

Anschließend können die Testfälle in eine Datei übernommen werden. Auch hier fehlt wieder der Kontext, da die Datei standardmäßig einfach im Hauptverzeichnis des Projektes abgelegt wird, zumindest bei der JetBrains-IDE-Integration.

Genutzt werden für Codium die OpenAI-Modelle der GPT-3 und GPT-4 Reihe. Interessant ist Codium für Plattformen, bei denen sonst keine IDE-Integration vorliegt, da Codium hier mit Vielfalt glänzt.

Neben dem Codeassistenten bietet Codium mit Forge auch eine Lösung für das Review von Quellcode an.

Cody

Mit Cody existiert ein KI-gestützter Assistent zur Softwareentwicklung. Nicht verwechselt werden sollte der Assistent mit Cody AI, das sich mehr als KI-unterstützte Suche auf Basis einer Firmen-Wissensbasis versteht.

Neben der Webvariante von Cody werden primär die Entwicklungsumgebungen VS Code und die JetBrains-IDEs unterstützt. Daneben existiert eine experimentelle Unterstützung für Neovim. Andere IDEs wie Eclipse und Emacs sollen in Zukunft folgen.

In der JetBrains-Variante wirkt die Integration ausgereift. So ist nicht nur ein Fenster verfügbar, in dem ein Chat angezeigt wird, sondern es existiert auch eine Integration im Code-Editor.

Anhand des Methodennamens wurde der Inhalt der Methode generiert

Während im Chatfenster der Kontext, wie die aktuell verwendete Programmiersprache nicht erkannt wird, sieht dies im Code-Editor anders aus. Hier wird der Code in der verwendeten Sprache generiert.

Die Modellauswahl im Chat-Fenster

Ein Merkmal, mit dem sich Cody von anderen KI-Assistenten unterscheidet, ist die transparente Auswahl der genutzten Modelle. Das passende Modell kann hierbei einfach ausgewählt werden.

Neben den Möglichkeiten zur Codegenerierung bietet Cody auch die Möglichkeit vorgefertigte Kommandos zu nutzen und mit diesen das Dokumentieren von Quellcode oder Unit-Test zu automatisieren.

CodeSquire

CodeSquire ist eine spezialisierte KI-Assistent-Lösung in Form einer Erweiterung für den Browser Chrome. CodeSquire ist ein Tool für Datenwissenschaftler, das Kommentare in Code umwandelt, SQL-Anfragen aus natürlicher Sprache erstellt, intelligente Codevervollständigung bietet und komplexe Funktionen generiert.

Unterstützt werden aktuell Plattformen wie Google Colab, BigQuery und JupyterLab.

Diese Plattformen zählen zu IDEs, die meist speziell für interaktive Datenanalyse und wissenschaftliches Rechnen genutzt werden. Diese speziellen IDEs kombinieren viele Funktionen, die in traditionellen IDEs zu finden sind, wie Code-Editoren, Terminals und Dateibrowser, mit speziellen Werkzeugen für die Arbeit mit Daten und interaktiven Notebooks.

CodeWP

Ebenfalls zu den spezialisierten Lösungen zählt CodeWP, welches einen Assistenten darstellt, welcher auf WordPress spezialisiert ist.

CodeWP

Die dahinterliegenden Modelle sind darauf trainiert, Code in PHP und JavaScript im Kontext von WordPress zu generieren. So kann mit einem einzelnen Prompt ein einfaches Plugin generiert werden.

Die CodeWP-Website

CodeWP erweckt mit Aussagen wie Proprietary AI und More accurate than ChatGPT sowie der Aussage:

Our Al models are trained to output the best, most modern, secure, simple code for WordPress. So no need to worry about common bugs or issues.

den Eindruck, dass ein eigenes Sprachmodel verwendet wird, ohne auf Mitbewerber wie OpenAI angewiesen zu sein.

Cursor

Cursor versteht sich, im Gegensatz zu den bisher vorgestellten Assistenten, als dedizierte IDE mit einer KI-basierten Unterstützung für Entwicklung.

Technisch handelt es sich um einen Fork von VS Code. Der Grund hierfür, ist nach Aussage des Herstellers, in der besseren Anpassbarkeit der IDE zu finden.

Der Onboarding-Prozess von Cursor

Nach der Installation wird der Nutzer durch einen kleinen Onboarding-Prozess geführt. Dieser führt in die Möglichkeiten ein, Bugs zu identifizieren, spezifische Codestellen zu lokalisieren oder Code von einer Programmiersprache in eine andere zu übersetzen.

Cursor kann natürliche Sprache verstehen und darauf reagieren, was es erleichtern soll, direkt im Code-Editor mit der KI zu interagieren. So können Fragen zu Codebasis gestellt werden, Vervollständigungen angefordert werden oder Code-Snippets generieren werden.

Die Freemium-Version unterliegt einigen Einschränkungen, welche in den kostenpflichtigen Tarifen aufgehoben werden.

Fraglich ist, ob hierfür eine neue IDE benötigt, und warum nicht auf Integrationen für bestehende Systeme gesetzt wurde. In den meisten Fällen werden Entwickler doch meist auf ihre angestammten Werkzeuge setzen wollen.

GitHub Copilot

Zu den bekannteren Lösungen auf dem Markt zählt sicherlich GitHub Copilot. Dieses Werkzeug ist in allen Varianten (bis auf die Trial-Version) kostenpflichtig.

Neben der Nutzung über die Kommandozeile, existieren eine Reihe von IDE-Integrationen, insbesondere für Visual Studio, VS Code und die JetBrains IDEs. Daneben werden Vim und Neovim, sowie Azure Data Studio unterstützt.

GitHub Copilot in einer JetBrains-IDE

Positiv fällt die Autovervollständigung bzw. die Geschwindigkeit derselben auf. Allerdings ist sie in einigen Fällen auch relativ nervig, da sie bei der Entwicklung zu unnötiger Ablenkung führen kann.

Eine Methode wird generiert

Zumindest in den JetBrains-IDEs gibt es keine Integration über die Quick-Fixes-Funktionalität. Dafür stehen eine Reihe von Kommandos wie /tests, /simplify, /fix oder /explain zur Verfügung.

Diese können in der eingebauten Chat-Funktionalität genutzt werden. Die Ergebnisse werden im Chat angezeigt, können allerdings nicht automatisch ins Projekt übernommen werden, sondern müssen kopiert und wieder eingefügt werden. Besonders nervig ist dies bei der Generierung von Dokumentation für Methoden, wie sich im Vergleich zum Assistenten JetBrains AI zeigt.

Positiv hervorzuheben ist die automatische Übernahme des Kontexts, wenn Themen im Chat angesprochen und genutzt werden.

JetBrains AI

Das tschechische Unternehmen JetBrains ist primär für seine unterschiedlichen IDEs bekannt und bietet mit JetBrains AI einen Assistenten für KI-unterstütze Entwicklung. Auch JetBrains AI muss über ein Abonnement freigeschaltet werden. Wenig verwunderlich ist die Integration von JetBrains AI in die jeweiligen IDEs der Firma sehr gelungen.

Entwicklung mit der JetBrains AI

Neben der bei vielen KI-Assistenten gegebenen Möglichkeiten des Chats mit dem Sprachmodell, bietet JetBrains AI die Möglichkeit von Quick-Fixes in Form von AI Actions, welche unter anderem das Schreiben von Dokumentation oder das Generieren von Unit-Tests vereinfachen sollen.

Neben den vorgefertigten Prompts können eigene Prompts hinterlegt und diese dann ebenfalls über die AI Actions genutzt werden. Angenehm an JetBrains AI ist die Möglichkeit Dokumentation wie Javadoc automatisch für eine Methode generieren und antragen zu können.

Die Einstellungen für JetBrains AI

Automatische Codevorschläge während der Entwicklung sind so gestaltet, dass sie nicht unnötig ablenken und können über die Einstellungen konfiguriert werden.

Daneben findet sich der KI-Assistent noch in anderen Integrationen wieder, wie bei der Umbenennung bzw. der Namensfindung, hier werden neben den klassischen Vorschlägen auch KI-Vorschläge angezeigt.

Durch ein kleines Symbol wird transparent gezeigt, welche Vorschläge von der KI stammen und welche nicht. Grundsätzlich zieht sich diese Transparenz durch JetBrains AI bzw. dessen Implementation.

Auch Fragen zu bestimmten Teilen des Quellcodes können schnell und bequem gestellt werden, indem an der gewünschten Stelle über eine Quick-Action ein KI-Chat zum aktuellen Quellcode gestartet wird.

Weitere Kleinigkeiten sind die Generierung von Commit-Nachrichten, welche ebenfalls von JetBrains AI bereitgestellt werden.

Während im Standard-Abonnement von JetBrains AI nicht gewählt werden kann, welche Sprachmodelle verwendet werden, soll dies später in den Enterprise-Varianten auswählbar sein. Je nach genutzter Funktionalität scheinen im Moment unterschiedliche Modelle genutzt werden.

Neben JetBrains AI, verfügen einige IDEs wie IntelliJ IDEA Ultimate mittlerweile auch über Möglichkeiten zur Codevervollständigung über ein lokales Sprachmodell, welches ohne externe Zugriffe auskommt.

Die IDE-Integration von JetBrains AI wirkt insgesamt sehr ausgereift, insbesondere im Vergleich zu anderen KI-basierten Assistenten. Dafür steht JetBrains AI nur für die entsprechenden IDEs der Firma zur Verfügung.

Tabnine

Die Firma hinter Tabnine existiert schon länger als der aktuelle KI-Hype und hat seit längerem Code-Assistenten zur Unterstützung in der Entwicklung angeboten.

Ursprünglich bekannt als Codota, hat sich das Unternehmen auf die Entwicklung von KI-basierten Werkzeugen für Entwickler spezialisiert. Im Gegensatz zu vielen anderen Lösungen wird bei Tabnine, über Tabnine Enterprise, auch das Selbst-Hosting angeboten.

Interessant ist bei Tabnine die Wahl der Modelle zur Verarbeitung der Anfragen. Hier werden Modelle wie Tabnine Protected angeboten, welche nur mit Quellcodes trainiert wurden, welche eine entsprechende Lizenz besitzen und somit idealerweise z. B. keine Codeschnipsel unter GPL replizieren.

Auch werden je nach Modell gewisse Garantien gegeben, was Themen wie Datenschutz und die Weiterverwendung der Prompts angeht. Daneben werden die Modelle über Tags sinnvoll kategorisiert, sodass die Wahl des passenden Modells aufgrund dieser getätigt werden kann.

Die Auswahl der Modelle

Bei den IDEs unterstützt Tabnine eine Reihe von IDEs, angefangen bei VS Code über die JetBrains-IDEs, bis hin zu Neovim.

Die Fix-Funktionalität von Tabnine

In Bezug auf die IDE-Integration wirkt Tabnine in JetBrains-IDEs recht gut integriert. Dadurch können kontextbasierte Operationen wie das Beheben von Fehlern oder das Dokumentieren von Quellcode effizient durchgeführt werden.

Im Tabnine-Chat wird dabei eine Antwort generiert und dessen Ergebnis kann mit in den Quellcode übernommen werden.

Das manuelle Einfügen fühlt sich allerdings immer etwas umständlich an und aktiviert oft die automatische Codeformatierung nicht, was im schlechtesten Fall immer einen zusätzlichen Bearbeitungsschritt bedeutet.

Die Generation eines Tests schlägt fehl

Andere Operationen, wie die Erstellung eines Testplans, können unter Umständen scheitern, da eine vom Plugin generierte Datei möglicherweise nicht befüllt werden kann, was auf einen Bug hinzudeuten scheint.

Die Testplan-Ideen von Tabnine

Auch wenn die Ideen für den Testplan von Tabnine interessant sind, fühlt sich hier die Integration durch das manuelle Einfügen komplex und fehleranfällig an.

Analyse-Werkzeuge

Neben den allgemeinen Code-Assistenten existieren einige Werkzeuge, welche sich auf die Analyse von Quellcode spezialisiert haben, z. B. für das Review von Quellcode bzw. Pull Requests.

Amazon CodeGuru

Ein von Amazon angebotenes Analyse-Werkzeug ist Amazon CodeGuru. Dieses Werkzeug versteht sich als Scanner, um Sicherheitslücken und Schwachstellen im Code zu finden. Daneben werden auch Vorschläge erstellt wie Anwendungen optimiert bzw. beschleunigt werden können.

Gedacht ist dieses Werkzeug nicht für die direkte Nutzung, sondern eher für die Integration in entsprechende Pipelines.

Neben der Nutzung in AWS CodeCommit (das demnächst eingestellt wird) wird auch die Nutzung von BitBucket- und GitHub-Repositories unterstützt.

Sourcery AI

Sourcery AI versteht sich als Werkzeug für automatisches Reviewing. Verknüpft werden kann dieses Werkzeug unter anderem mit GitHub oder GitLab. Wenn gewünscht, wird so bei jedem Pull-Request ein entsprechender Kommentar hinterlassen.

Sourcery AI erstellt Kommentare zu einem Pull Request

Während die Nutzung für kommerzielle Projekte mit einem Abonnement verbunden ist, können Open-Source-Projekte Sourcery AI ohne weitere Kosten einsetzen.

Neben der Kommentierung des Pull-Requests werden auch Hinweise für den Reviewer und eine Zusammenfassung erstellt.

Snyk

Neben Werkzeugen, die sich auf normale Entwicklungsarbeiten konzentrierten, existiert mit Snyk ein Analyse-Werkzeug, welches Verwundbarkeiten und Sicherheitsprobleme im Code aufdecken soll.

Snyk in einer JetBrains IDE

Snyk positioniert sich als Werkzeug, das durch den Einsatz von maschinellem Lernen sowie dynamischen und statischen Analysen den Quellcode auf diese Problemklasse hin untersucht.

Dabei werden eine Reihe von Produkten angeboten, welche diese Technologie zur Anwendung bringen soll.

WhatTheDiff

Ähnlich wie Sourcery AI ist auch WhatTheDiff ein Werkzeug für automatisierte Code-Reviews.

Im Gegensatz zu Sourcery AI muss die GitHub-Integration vor der Nutzung konfiguriert und aktiviert werden.

Die Repositories müssen aktiviert werden

Nach der Aktivierung werden für Pull Requests automatisch Kommentare erzeugt.

What The Diff erzeugt automatisch Kommentare zu den Pull Requests

Wie bei Sourcery AI werden hier auch Kommentare zur Zusammenfassung und Review-Kommentare am Pull Request erstellt, welche dann bearbeitet werden können.

Weitere Werkzeuge

Neben den größeren Klassen wie Code-Assistenten und Analysewerkzeuge, existieren weitere Werkzeuge, welche KI-basiert einen Mehrwert in der Entwicklung bringen können.

bloop.ai

Unter bloop.ai werden verschiedene Services rund um KI-gestützte Codegenerierung und Nutzung angeboten.

So wird ein Dienst angeboten, welcher COBOL-Programme in lesbare Java-Applikationen umwandeln soll. Ein weiterer Dienst befasst sich mit einem Sprachmodell, welches direkt COBOL-Quellcode schreiben kann.

bloop indiziert ein Repository

Für den alltäglichen Gebrauch interessanter war die Understand-Funktionalität, die es ermöglicht, Repositories zu laden und anhand dieser Repositories Fragen zum Quellcode zu stellen.

Bloop wird zum Bevy-Projekt befragt

Diese existierte in einer freien Variante sowie in einer kostenpflichtigen Personal-Variante. In der kostenpflichtigen Variante wurde unter anderem die Indizierung mehrerer Branches ermöglicht.

Nach der kürzlich erfolgten Einstellung steht nur noch die freie Variante dieser Funktionalität zur Verfügung. Für den alltäglichen Gebrauch, vorwiegend mit unbekannteren Codebasen, kann dieses Werkzeug eine wertvolle Ergänzung sein.

GitFluence

Wer in der Softwareentwicklung arbeitet, wird oft auch mit Versionskontrollsystemen wie Git arbeiten. Auch hier existieren mittlerweile KI-Tools, welche unterstützen sollen.

GitFluence

Eines dieser Werkzeuge ist GitFluence, das unter der Haube mit der OpenAI-API arbeitet. Gedacht ist das Werkzeug für den Fall, dass eine Git-Aktion beschrieben wird und automatisch ein Git-Kommando dafür erstellt wird.

Dies wirkt allerdings in einigen Fällen eher unausgegoren und lieferte unbrauchbare Ergebnisse, während es sporadisch sinnvolle Antworten liefert.

Grit.io

Der Dienst Grit.io spezialisiert sich auf Code-Migration und automatische Dependency Upgrades. Aktuell ist er nur über eine Warteliste verfügbar, sodass hier eine genauere Beurteilung schwerfällt.

Eines der Beispiele von der Grit.io-Seite

Durch die automatische Aktualisierung von Abhängigkeiten und die Durchführung größerer Migrationen soll eine allgemeine Verbesserung der Codequalität stattfinden.

Mutable AI

Neben Code-Assistenten, die sich auf die Entwicklung spezialisieren, existieren auch solche Assistenten, die sich der Dokumentation und Schaffung einer Wissensbasis zur entwickelten Software verschrieben haben. Zu diesen Diensten gehört Mutable AI.

Eine Mutable AI-Wiki

Nach Abschluss eines Abonnements ist es möglich zu einem Repository ein automatisches Wiki zur Dokumentation zu erstellen. Neben dieser Art der Dokumentation kann die Codebasis auch über einen KI-Assistenten befragt werden.

Die Dokumentation wird automatisch bei Änderungen des Repositories aktualisiert.

SQLAI.ai

Für die Arbeit mit SQL und Datenbanken existieren eine Reihe von KI-Werkzeugen wie SQLAI.ai. Mithilfe dieser Werkzeuge können Abfragen erzeugt, überprüft und auf Fehler untersucht werden.

SQLAI

Im Wesentlichen generieren die meisten dieser Werkzeuge, häufig unter Einbeziehung zusätzlicher Informationen wie des Datenbankschemas, passende Eingaben für das verwendete Sprachmodell. Zusätzliche Metainformationen wie das Datenbankschema, helfen hierbei sinnvolle Ausgaben für die eigenen Projekte zu erzeugen.

Ein ähnliches Werkzeug ist AI Query, das ebenfalls über Werkzeuge zur SQL-Prüfung und Bearbeitung verfügt. Daneben existieren eine Vielzahl anderer Werkzeuge dieser Art wie TEXT2SQL oder AI2sql.

Über den Tellerrand

Neben all diesen Werkzeugen existieren weitere Ansätze und Möglichkeiten, welche die Entwicklung und Prozesse der Softwareentwicklung vereinfachen sollen.

So existiert mit Stepsize AI ein Werkzeug, welches Sprint Reports im Kontext der agieren Softwareentwicklung erzeugen soll oder mit Bugasura ein Bug-Tracker mit KI-Unterstützung.

Neben kommerziellen Lösungen, welche auf entsprechende Modelle von OpenAI und Co. setzen, existieren auch freie Modelle zur Entwicklung von Software.

Eines dieser Modelle ist PolyCoder, welches auf Basis von GPT-2, mit einem Korpus von über zwölf Programmiersprachen trainiert wurde. Ähnliches vermag CodeGeeX zu leisten, welches aus dem asiatischen Raum stammt.

Allerdings lassen sich diese Systeme nicht so einfach nutzen wie die vorkonfektionierten Angebote, kommerzieller Anbieter. Es muss ein entsprechender Setup-Aufwand geleistet werden, bevor die Modelle genutzt werden können. Darüber hinaus ist die Performanz lokal ausgeführter Modelle, aufgrund der genutzten Hardware, oft unzureichend.

Fazit

Sprachmodelle konnten für die Entwicklung bereits genutzt werden, bevor es spezielle Integrationen dafür gab. Dafür musste der Entwickler Prompts definieren und diese mit dem Quelltext in das Modell geben.

Viele Integrationen nehmen dem Entwickler das Schreiben des Prompts in vielen Fällen ab und ermöglichen so eine schnellere Nutzung der Modelle. Bedingt durch die zugrundeliegenden Sprachmodelle werden viele Programmiersprachen auch von den vorgestellten Werkzeugen unterstützt.

Damit können in der Theorie viele Standardaufgaben, wie die Dokumentation, Unit-Tests oder auch komplexere Dinge wie die Konvertierung zwischen zwei Programmiersprachen mehr oder weniger vereinfacht werden. Allerdings sollten die Ergebnisse dieser KI-basierten Assistenzfunktionen immer bewertet und analysiert werden und nicht einfach ungeprüft übernommen werden. Spätestens bei komplexeren Problemen, welche ein umfassenderes Verständnis über die Codebasis benötigen, versagen die KI-Assistenten in vielen Fällen.

Aktuell existieren auf dem Markt eine unzählige Anzahl von KI-Werkzeugen und jeden Tag werden es mehr. Einige dieser Werkzeuge werden wieder verschwinden, während andere Werkzeuge erhalten bleiben. Auch in Zukunft sollen KI-Assistenten weiter integriert werden, wie in XCode von Apple.

Für Code-Assistenten sowie zahlreiche andere Werkzeuge gilt, dass sie im Wesentlichen auf ähnliche Weise funktionieren: Ein beliebiger Prompt wird erstellt, an ein Sprachmodell übermittelt und von diesem verarbeitet.

Hier stechen am Ende nur Lösungen hervor, welche eine gute Integration bieten und es somit dem Entwickler nicht unnötig schwer machen, die Assistenzfunktionen im Arbeitsalltag anzuwenden.

Positiv haben neben der Integration der JetBrains AI die Codesuche über Bloop überrascht, bei welcher zu einer Codebasis Fragen gestellt werden können und diese Codebasis damit genauer und schneller kennengelernt werden kann.

Neben den praktischen Aspekten sollte auch beachtetet werden, dass ein Großteil der aktuellen KI-Lösungen kostenpflichtig sind und ihren Gegenwert einspielen müssen.

Abgesehen von den monetären Aspekten gilt es auch den Datenschutz zu beachten, schließlich werden in vielen Fällen vertrauliche Daten an Drittservices gesendet und dort verarbeitet.

Daneben ist die Datenbasis prinzipbedingt immer leicht veraltet. So können Informationen zu neuen Versionen einer Software z. B. zur Game Engine Bevy über viele Sprachmodelle nicht bezogen werden, da ihr Trainingsdatum vor dem Erscheinungsdatum der neuen Softwareversion liegt.

Ob sich die Technologie in Zukunft einen wirklichen Mehrwert in der Entwicklung bringt, wird sich zeigen. Gegenwärtig scheint es so, dass sich ein Teil der KI-Werkzeuge sich dem Plateau der Produktivität im Hype-Zyklus nähert.

Bei einer guten und niederschwelligen Integration kann damit vielleicht das ein oder andere KI-basierte Werkzeug seinen Weg in den Werkzeugkasten der Softwareentwicklung finden.

Dieser Artikel erschien ursprünglich auf Golem.de und ist hier in einer alternativen Variante zu finden.

Markdown – einfach und vielseitig

Wer Text schreibt, kann dies mit unterschiedlichen Werkzeugen bewerkstelligen, vom WYSIWYG-Editor à la Word bis hin zum reinen Texteditor. Jede dieser Varianten wartet mit unterschiedlichen Vor- und Nachteilen auf.

Daneben hat in den vergangenen Jahren die Nutzung der Auszeichnungssprache Markdown zugenommen und diese an Beliebtheit gewonnen. Im Gegensatz zum What You See Is What You Get-Ansatz trennt Markdown die Struktur und Formatierung vom endgültigen Erscheinungsbild, indem es die Bedeutung des Inhaltes betont. Trotzdem lässt sich ein solcher Markdown-Text auch ohne weitere Kenntnisse problemlos lesen:

# Überschrift

Lorem *ipsum dolor sit amet*, consectetur, adipisci 
velit, ut aspernatur labore ad dolores quidem eos
architecto pariatur. Dolor asperiores commodi corrupti, 
vel dignissimos velit, **labore aliquip voluptatem**:

* Lorem
* Ipsum
* dolor

## Noch eine Überschrift

Lorem ipsum dolor sit amet:

> Sequi quasi mollit dolor cupiditate in.

Somit stört Markdown den Lesefluss nicht und enthält doch Informationen über die Struktur des Dokumentes. Doch wie genau wird Markdown geschrieben, genutzt und wo finden sich seine Einsatzgebiete?

Auszeichnungssprachen

Markdown wird den Auszeichnungssprachen zugeordnet. Bei solchen Auszeichnungssprachen (engl. Markup language), handelt es sich um eine Sprache, die zur Strukturierung, Formatierung und Kennzeichnung von Texten und Daten verwendet wird.

Eine solche Sprache ermöglicht es, Textinhalte mit zusätzlichen Informationen zu versehen, die deren Struktur und Darstellung definieren. Diese zusätzlichen Informationen werden in Form von Tags oder Markierungen eingefügt, die wiederum von anderen Programmen, z. B. Browsern interpretiert werden können.

Zu den bekanntesten Auszeichnungssprachen gehört HTML:

<html>
<head>
  <title>Beispielseite</title>
</head>
<body>
  <h1>Lorem Ipsum</h1>

  Lorem ipsum dolor sit amet.
</body>
</html>

Geschichte

Historisch gesehen geht die Entwicklung von Markdown auf das Jahr 2004 zurück, in welchem John Gruber und Aaron Swartz diese Entwicklung anstießen. Aaron Swartz hatte vorher mit atx eine eigene Auszeichnungssprache definiert, aus der unter anderem die Überschriften-Semantik in Markdown übernommen wurde.

Die Hauptidee hinter Markdown war es, eine einfache Möglichkeit zu schaffen, Text in HTML zu konvertieren, ohne dass der Nutzer umfangreiche HTML-Kenntnisse benötigt. Gruber und Swartz wollten damit eine Sprache schaffen, die leicht zu lesen und zu schreiben ist. John Gruber fasste dies mit der Aussage:

Markdown is intended to be as easy-to-read and easy-to-write as is feasible.

in der ursprünglichen Markdown-Spezifikation zusammen. Inspiriert wurde die Syntax und der Aufbau von Markdown von bereits vorher verwendeten Konventionen, wie der Textauszeichnung in E-Mails und anderen Auszeichnungssprachen wie Textile.

Neben der ursprünglichen Spezifikation wurde auch ein Perl-Skript mit dem Namen Markdown.pl entwickelt, welches Markdown in HTML konvertieren konnte. Das Skript und die dazugehörige Dokumentation wurden unter der 3-Klausel BSD-Lizenz veröffentlicht und sind damit freie Software. Die einfache Syntax und die Möglichkeit, Markdown-Dateien in verschiedenen Umgebungen zu verwenden, machten es schnell populär.

Ein wesentlicher Aspekt von Markdown ist seine Lesbarkeit. Die Syntax ist so gestaltet, dass der Text auch dann lesbar bleibt, wenn er nicht in HTML umgewandelt wird. Dies unterscheidet Markdown von anderen Auszeichnungssprachen wie LaTeX oder HTML, die ohne entsprechende Rendering-Tools oft schwer zu lesen sind. Diese Eigenschaft machte Markdown besonders attraktiv für Blogger, Autoren und Entwickler, die ihre Texte sowohl in Rohform als auch in gerenderter Form verwenden wollten.

Mit der Zeit entwickelte sich Markdown zu einem De-facto-Standard für Textformatierung im Web. Viele Blogging-Plattformen, Content-Management-Systeme und Plattformen wie GitHub begannen, Markdown zu unterstützen.

GitHub spielte eine entscheidende Rolle bei der Popularisierung von Markdown, indem es die Sprache für die Dokumentation von Projekten und das Schreiben von README-Dateien bzw. README.md-Dateien verwendete. Dies führte dazu, dass immer mehr Entwickler und Autoren Markdown in ihren Arbeitsabläufen integrierten.

Trotz seiner Popularität gab es keine offizielle Standardisierung von Markdown, was zu verschiedenen Dialekten und Implementierungen führte. Dadurch entstanden Kompatibilitätsprobleme, da verschiedene Systeme und Tools unterschiedliche Varianten von Markdown unterstützten. Um diesem Problem zu begegnen, wurde 2014 das Projekt CommonMark ins Leben gerufen. CommonMark zielt darauf ab, eine einheitliche Spezifikation für Markdown zu schaffen und so die Kompatibilität zwischen verschiedenen Implementierungen zu verbessern.

Nicht unerheblich für den Erfolg von Markdown war die Entwicklung von entsprechenden Konvertern. Software wie Pandoc ermöglichte es Benutzern, Markdown-Dokumente in verschiedene Formate zu konvertieren. Diese Werkzeuge erweiterten die Einsatzmöglichkeiten von Markdown erheblich, indem sie den Export von Markdown-Dokumenten in PDF-, Word- und andere Formate ermöglichten.

Die Flexibilität von Markdown führte zu seiner Verwendung in anderen Bereichen, wie z. B. in wissenschaftlichen Publikationen, technischen Dokumentationen und sogar in Präsentationen. Durch die Integration von Erweiterungen wie MathJax für mathematische Formeln konnte Markdown an die spezifischen Bedürfnisse verschiedener Benutzergruppen angepasst werden.

Syntax

Grundsätzlich handelt es sich um bei einem Markdown-Dokument um ein normales Textdokument, welches über verschiedene Zeichen strukturiert wird. So befinden sich im folgenden Dokument eine Überschrift der ersten Ebene und ein Text, in welchem ein Wort kursiv gestellt wird:

# Lorem Ipsum

Lorem Ipsum dolor *sit* amet.

In Markdown existieren verschiedene Arten von Blöcken, die zur Strukturierung und Formatierung von Text verwendet werden. Grundlegend können Blöcke in Markdown in zwei Typen unterteilt werden: Containerblöcke und Blattblöcke (engl. leaf blocks).

Containerblöcke dienen als übergeordnete Strukturen, die mehrere Elemente umfassen können. Blattblöcke hingegen sind Blöcke, die keine anderen Blöcke enthalten können. Sie sind die „Blätter“ der Dokumentstruktur und enthalten den eigentlichen Inhalt.

Zu den Containerblöcken gehören Absätze, Blockzitate, Listen und Codeblöcke. Zu den Blattblöcken gehören Überschriften, horizontale Linien, Inline-Code und HTML-Blöcke.

Eines der einfachsten Elemente in Markdown ist der Absatz. Dieser definiert sich als eine Ansammlung von Zeilen. Getrennt werden diese Absätze durch eine oder mehrere leere Zeilen. In der Denkweise von Markdown bedeutet dies, dass wenn die Zeile leer aussieht, sie leer ist. So würde eine Zeile gefüllt mit Leerzeichen oder Tabs als leer interpretiert werden.

Ein grundlegendes Merkmal von Markdown ist die Verwendung von Klartextzeichen, um Formatierungen zu definieren. Überschriften können etwa durch Voranstellen einer Raute erstellt werden.

Mit einer einzelnen Raute kann so eine Überschrift der ersten Ebene, mit zwei Rauten eine Überschrift der zweiten Ebene usw. definiert werden. Bei einer Konvertierung in HTML würde hierbei die Tags <h1> und <h2> generiert werden:

# Überschrift der ersten Ebene

## Überschrift der zweiten Ebene

### Überschrift der dritten Ebene

Diese Art der Überschriften wird auch atx-Überschrift genannt. Daneben werden in der ursprünglichen Markdown-Spezifikation auch Setext-Überschriften definiert. Setext-Überschriften werden durch das Unterstreichen des Überschriftentextes erzeugt:

Überschrift der ersten Ebene
============================

Überschrift der zweiten Ebene
-----------------------------

In der Praxis kommt heute zumeist die atx-Variante zum Tragen, mit welcher bis zu sechs Ebenen definiert werden können. Weniger bekannt ist, dass diese Art der Überschrift auch geschlossen existieren darf:

# Überschrift (Ebene 1) #

Lorem Ipsum dolor sit amet.

## Überschrift (Ebene 2) ##

Die Nutzung der schließenden Rauten ist hierbei rein kosmetischer Natur und hat sonst keinerlei Auswirkungen. Allerdings sollte beachtet werden, dass diese geschlossene Variante nur selten genutzt und von vielen Markdown-kompatiblen Werkzeugen in dieser Form nicht unterstützt wird.

Da Markdown ursprünglich zur Konvertierung in HTML gedacht war, dieses aber nicht ersetzen sollte, verfügt es über die Möglichkeit Inline-HTML zu nutzen:

# Hypergraphen

Ein Hypergraph ist eine Verallgemeinerung eines Graphen.

# Begrifflichkeiten

Folgende Begrifflichkeiten definieren einen solchen Graphen:

  <table>
        <tr>
            <th>Eigenschaft</th>
            <th>Beschreibung</th>
        </tr>
        <tr>
            <td>Knoten</td>
            <td>Die grundlegenden Einheiten eines Hypergraphen, ähnlich den Knoten in einem einfachen Graphen.</td>
        </tr>
        <tr>
            <td>Kanten</td>
            <td>Kanten in einem Hypergraphen, auch Hyperkanten genannt, können mehr als zwei Knoten verbinden.</td>
        </tr>
    </table>

Neben Hypergraphen ...

Sollen in Markdown Zeichen genutzt werden, welche durch die Markdown-Syntax vorbelegt sind, so müssen diese Zeichen maskiert werden. Dies geschieht mit dem Backslash:

\# Dies ist keine Überschrift

Für Hervorhebungen kennt Markdown die Möglichkeit, Text als fett und kursiv zu markieren. Um einen Text kursiv zu setzen, reicht es aus ihn in Sternchen zu setzen:

*kursiv*

Soll der Text hingegen fett gesetzt sein, so werden zwei Sternchen benötigt:

**fett**

Auch die Kombination aus Kursiv- und Fettschreibung ist möglich, indem drei Sternchen genutzt werden:

***kursivundfett***

Neben der Nutzung des Sternchens ist auch die Nutzung von Unterstrichen möglich. Allerdings wird dies in der Praxis seltener genutzt.

Neben diesen einfachen Formatierungen sind in Markdown Blöcke wie Zitate und Beispielcodeblöcke möglich. So beginnt ein Zitat in Markdown mit einer spitzen Klammer:

> There is no reason for any individual to have a computer in his home.
> Ken Olsen, 1977

Hierbei ist auch erlaubt, diese Blöcke ineinander zu verschachteln, sodass verschachtelte Zitate dargestellt werden können:

> Er pflegte es immer mit einem Zitat zu begründen:
> > Wenn Sterne tanzen, ihre Glut sich erhebt.

Codeblöcke können in Markdown ebenfalls abgebildet werden. Dazu muss der entsprechende Code mit vier Leerzeichen bzw. einem Tab eingerückt werden. Damit wird ein solcher Block als preformatierter Text betrachtet.

Alternativ kann ein Codeblock auch über drei Backticks erzeugt werden:

```
int number = 13052025;

if(isPrime(number)) {
    ...
}
```

Markdown unterstützt Listen. Hierbei wird zwischen ungeordneten und geordneten Listen unterschieden. Ungeordnete Listen können mit einem Sternchen erzeugt werden:

# Einkaufsliste

* Brot
* Marmelade
* Salat

Daneben können solche Listen auch mit einem Plus- oder einem Minus-Zeichen angelegt werden.

Für geordnete Listen muss eine Zahl vor den eigentlichen Listenpunkt geschrieben werden:

# Prioritäten

1. Rasen mähen
2. Einkaufen
3. Kochen

Die Zahlen zur Nummerierung müssen nicht unbedingt aufeinanderfolgen; dies dient nur der besseren Lesbarkeit. In der Theorie könnte eine solche Liste auch wie folgt aussehen:

# Prioritäten

1. Rasen mähen
1. Einkaufen
1. Kochen

Würde ein solches Markdown-Element in eine HTML-Datei konvertiert werden, so würde ein Dokument aus einem <ol>-Tag mit einer entsprechenden Liste bestehen. Die Nummern würden in diesem Fall bei der Konvertierung entfallen.

Markdown ermöglicht auch das Einfügen von horizontalen Linien, die als Trennlinien verwendet werden können. Dies geschieht durch mindestens drei Bindestriche, Sternchen oder Unterstriche in einer separaten Zeile. Diese Trennlinien sind nützlich, um verschiedene Abschnitte eines Dokumentes visuell und thematisch zu trennen.

Neben Formatierungen können in Markdown auch Verlinkungen und Bilder integriert werden. Ein Link wird durch eckige Klammern für den Linktext und runde Klammern für die URL definiert:

[Linktext](http://example.com)

Diese Links werden auch Inline-Links genannt. Markdown ermöglicht daneben, Links auf eine elegantere Weise zu verwalten, insbesondere wenn dieselbe URL mehrfach verwendet wird. Dies geschieht durch die Verwendung von Referenz-Links. Ein Referenz-Link wird in zwei Teilen geschrieben: Der erste Teil enthält den Link-Text und eine Referenz in eckigen Klammern:

[Beispiel-Link][1]

Nun muss dazu die entsprechende Referenz definiert werden:

[1]: https://www.example.com

Diese Methode verbessert die Lesbarkeit des Quelltextes und erleichtert die bessere Verwaltung von Links, da die URL nur einmal geändert werden muss, wenn sie aktualisiert wird.

Neben der Verlinkung zu externen Webseiten ermöglicht Markdown auch das Verlinken zu anderen Teilen desselben Dokumentes, was besonders nützlich für lange Texte oder Dokumentationen ist. Dies wird durch die Verwendung von Anker-Links erreicht. Ein Anker-Link verweist auf eine bestimmte Überschrift im Dokument. Beispielhaft könnte dies so aussehen:

[Einleitung](#einleitung)

Damit würde dieser Link auf die Überschrift Einleitung verweisen.

Eine eher selten genutzt Möglichkeit der Verlinkung sind sogenannte Autolinks. Damit können URLs und E-Mail-Adressen automatisch in Links umgewandelt werden. Dazu muss die betreffende URL oder E-Mail-Adresse in spitze Klammern gesetzt werden:

<example.com>

Die Syntax zur Einbindung von Bildern ähnelt der von Verlinkungen. Jedoch wird ein Ausrufezeichen vor der Definition genutzt:

![Alt-Text](http://example.com/bild.jpg)

Auch die Angabe eines Titels ist bei dieser Art der Definition möglich:

![Alt-Text](http://example.com/bild.jpg "Titel des Bildes")

Daneben sind wie bei der Verlinkung auch bei der Definition von Bildern die Möglichkeiten von Referenzen gegeben.

Neben den klassischen Elementen, die in Markdown dargestellt werden können, existieren auch Elemente, welche durch verschiedene Erweiterungen bzw. Varianten, wie GitHub Flavored Markdown, zu Markdown kamen.

In diesen Erweiterungen können unter anderem Tabellen definiert werden. Tabellen können erstellt werden, indem Spalten durch senkrechte Striche und Zeilen durch Zeilenumbrüche getrennt werden. Die Kopfzeile wird durch eine Trennlinie aus Bindestrichen unterstrichen. Diese Syntax macht es einfach, strukturierte Daten darzustellen.

Eine solche Tabelle könnte beispielhaft wie folgt aussehen:

| Spalte 1 | Spalte 2 | Spalte 3 |
|----------|----------|----------|
| Inhalt 1 | Inhalt 2 | Inhalt 3 |
| Inhalt 4 | Inhalt 5 | Inhalt 6 |

Auch eine Syntax für Fußnoten ist im ursprünglichen Markdown nicht vorgesehen, wurde aber in unterschiedlichsten Varianten definiert:

Das ist ein Beispieltext mit einer Fußnote.[^1]

[^1]: Dies ist der Text der Fußnote.

Komplexer wird es bei der Integration von mathematischen Formeln in Markdown. Hier sind unterschiedliche Möglichkeiten gegeben, wie die Nutzung von MathJax oder direkte Unterstützung der LaTeX-Syntax für Formeln, die allerdings nur in bestimmten Varianten und Markdown-Werkzeugen unterstützt werden.

Geschmacksrichtungen

Standard-Markdown, oft einfach Markdown genannt, ist die ursprüngliche Version, die von John Gruber veröffentlicht wurde. Es bietet grundlegende Formatierungsoptionen wie Überschriften, Listen, Links, Bilder und Zitate.

Daneben existieren Markdown-Varianten, welche unterschiedlichste Formatierungsmittel und Möglichkeiten hinzufügen. Diese Varianten erweitern die ursprüngliche Markdown-Syntax und bieten zusätzliche Funktionen, um den unterschiedlichen Anforderungen der Benutzer gerecht zu werden. Jede Variante hat ihre eigenen spezifischen Anwendungsfälle und wird in verschiedenen Kontexten bevorzugt.

Zu den häufigsten Varianten zählen GitHub Flavored Markdown, CommonMark, Markdown Extra, MultiMarkdown und die Pandoc-Markdown-Variante, wobei CommonMark im Verlauf des Artikels noch separat betrachtet werden soll.

Varianten unter der Lupe

GitHub Flavored Markdown ist eine erweiterte Version von Markdown, die von GitHub entwickelt wurde. Sie fügt zusätzliche Funktionen hinzu, die speziell auf die Bedürfnisse von Entwicklern und die Nutzung auf GitHub zugeschnitten sind. Zu den Erweiterungen gehören Tabellen, erweiterte Listen, Inline-Code, Codeblöcke mit Syntaxhervorhebung und Task-Listen.

Markdown Extra ist eine Erweiterung, die von Michel Fortin entwickelt wurde. Es fügt zusätzliche Funktionen wie Definition Lists, Fußnoten, Abkürzungen und Tabellen hinzu.

MultiMarkdown wurde von Fletcher Penney entwickelt und erweitert die Fähigkeiten von Markdown um Funktionen wie Tabellen, Fußnoten, Referenzen und mathematische Unterstützung. Es ist besonders nützlich für wissenschaftliche und technische Dokumentationen.

Neben diesen Varianten existieren weitere Markdown-Varianten, wie RMarkdown und kramdown, welche hier allerdings nicht weiter behandelt werden sollen.

Standardisierung

Die ursprüngliche Markdown-Spezifikation von John Gruber kämpft mit einigen Mehrdeutigkeiten. Daneben wurden im Laufe der Zeit, wie oben beschrieben, eigene Varianten und Erweiterungen von Markdown entwickelt. Diese Varianz führte zu Problemen beim Teilen und Verarbeiten von Markdown-Dokumenten.

Im Jahr 2012 initiierte eine Gruppe von Personen, zu der Jeff Atwood und John MacFarlane gehörten, eine Standardisierungsinitiative. Eine Community-Website wurde erstellt, um eine Vielzahl von Werkzeugen und Ressourcen zu dokumentieren, die Autoren von Dokumenten und Entwicklern verschiedener Markdown-Implementierungen zur Verfügung stehen sollten.

Im September 2014 äußerte Gruber Bedenken hinsichtlich der Nutzung des Namens Markdown für diese Initiative, woraufhin sie in CommonMark umbenannt wurde.

CommonMark veröffentlichte mehrere Versionen einer Spezifikation, einer Referenzimplementierung und einer Testsuite und plant eine endgültige 1.0-Spezifikation vorzustellen. Diese 1.0-Spezifikation wurde jedoch bisher nicht veröffentlicht, da noch wichtige Probleme ungelöst sind.

Einige Projekte haben mittlerweile die Definition von CommonMark übernommen darunter Discourse, GitHub, und Stack Exchange.

Vom CommonMark-Projekt werden unterschiedlichste Parser angeboten, wie commonmark-java, welche wiederum Erweiterungen unterstützen. Daneben existieren andere Parser, welche ebenfalls die CommonMark-Spezifikation implementieren, z. B. markdown-it.

Auch wenn sich CommonMark in vielen Bereichen durchgesetzt hat, ist die Vielfalt und Unterschiedlichkeit der Markdown-Derivate, schon im Ursprung von Markdown angelegt, neben den anderen Problemen, welche oft mit der Definition eines Standards eingehen.

RFCs

Daneben fand Markdown auch bereits Erwähnung in einigen RFCs. Im März 2016 wurden zwei relevante RFCs veröffentlicht: RFC 7763 führte den MIME-Typ text/markdown ein, und RFC 7764 diskutierte unter anderem die Varianten MultiMarkdown, GitHub Flavored Markdown, Pandoc und Markdown Extra.

Markdown in der Praxis

Doch wie sieht die Nutzung von Markdown in der Praxis aus? Hier haben sich in den vergangenen Jahren viele Gebiete gefunden, in denen Markdown genutzt wird.

Texteditoren und IDEs

Viele Entwicklungsumgebungen und Texteditoren unterstützen Markdown mittlerweile von Haus aus. Dies bedeutet meist ein (optionales) Rendering und eine Hervorhebung der Formatierungselemente, wie bei der Fett- und Kursivstellung von Texten. Im Rahmen von Textdateien wird als Endung für Markdown-Dateien überwiegend die Endung .md genutzt.

Markdown-Editor in IntelliJ IDEA

So unterstützen IDEs wie die JetBrains IDEs und Editoren wie Atom, Visual Studio Code oder auch Texteditoren wie Notepad++, Sublime Text oder TextMate Markdown.

Markdown-Unterstützung in TextMate

Daneben existieren mit Editoren wie MarkText, Anwendungen welche speziell auf Markdown geeicht sind. Dieser Editor bietet eine Echtzeit-Vorschau, Unterstützung für CommonMark und GitHub Flavored Markdown sowie eine Vielzahl von Themes und Tastenkombinationen.

Zusätzlich zu den beschriebenen Texteditoren existieren auch webbasierte Markdown-Editoren wie Dillinger.

Der Markdown-Editor Dillinger

Auch dieser Editor bietet eine Echtzeit-Vorschau und die Möglichkeit, Dokumente in unterschiedliche Formaten zu exportieren.

Notiz-Applikationen

Neben reinen Texteditoren und IDEs haben sich mittlerweile auch viele Notiz-Applikationen für Markdown erwärmt.

Während die Unterstützung bei Apps wie Evernote und OneNote eher eingeschränkt ist, oder nur durch Plugins ermöglicht wird, existieren andere Applikationen wie Bear, Joplin oder Obsidian, die sich weitgehend auf Markdown stützen.

Joplin nutzt Markdown als Basis

Markdown dient hier als schneller und unkomplizierter Weg, Informationen zu erfassen. Je nach Applikation werden unterschiedliche Ansichten auf die Markdown-Dokumente geliefert, wie zum Beispiel das Quelldokument und das entsprechende Rendering. Bei Joplin werden auch Webseiten in Markdown konvertiert, wenn sie mit dem Webclipper gespeichert wurden.

Blogging und Content Management

Viele Blogging-Plattformen wie WordPress, Ghost und Jekyll unterstützen Markdown, was es Autoren ermöglicht, sich auf das Schreiben zu konzentrieren, ohne sich um die Formatierung zu sorgen.

Da Markdown-Dateien ursprünglich darauf angelegt waren, einfach in HTML umgewandelt zu werden, vereinfacht dies die Veröffentlichung im Web.

Je nach verwendetem System werden hier, wie im Falle von WordPress, Plugins für die Unterstützung benötigt. Andere Systeme wie Ghost und Jekyll unterstützen Markdown nativ.

Dokumentation und technisches Schreiben

Besonders beliebt ist Markdown in der Softwareentwicklung für die Erstellung von Dokumentationen.

Plattformen wie GitHub verwenden Markdown für README-Dateien, die Projektdetails und Anweisungen enthalten. Mit Markdown können Entwickler schnell und effizient Dokumentationen erstellen und aktualisieren.

# Java Starter Project

Starter project for Java based on Maven. Generates a fat JAR file containing all dependencies. JAR files are created with:

> mvn package

## Dependencies

Includes some basic dependencies:

* Guava
* GSON
* SLF4J
* JUnit (Version 5)

...

Neben der Dokumentation in Softwareprojekten existieren eine Reihe von Dokumentationstools.

Eine aus Markdown erzeugte Mkdocs-Dokumentation

So setzen Werkzeuge wie MkDocs und Sphinx auf Markdown und auch Plattformen wie ReadTheDocs unterstützen Markdown.

E-Mails und Kommunikation

Markdown kann zum Schreiben von E-Mails verwendet werden, um Text klar und strukturiert zu formatieren. Einige E-Mail-Clients unterstützen Markdown direkt. So existieren Clients wie MailMate, die Markdown nativ zum Schreiben von E-Mails unterstützen.

Auch etablierte Mail-Clients wie Thunderbird können über Add-Ons wie Markdown Here mit einer entsprechenden Funktionalität nachgerüstet werden.

Präsentationen

Mittels entsprechender Frameworks und wie reveal.js können auch Präsentationen über Markdown erstellt werden.

Reveal.js ist ein Open-Source-Framework zur Erstellung von Präsentationen im Webbrowser. Entwickelt von Hakim El Hattab, ermöglicht es Nutzern, ansprechende und interaktive Präsentationen mit HTML, CSS und JavaScript, aber auch mit Markdown zu gestalten.

Dadurch kann sich der Ersteller einer Präsentation auf die Inhalte konzentrieren, ohne sich mit Designfragen auseinandersetzen zu müssen.

Eine reveal.js Präsentation

Dazu müssen die Markdown-Dateien nur innerhalb der Index-Datei der reveal.js-Präsentation eingebunden werden:

<div class="slides">
    <section data-markdown="markdown/intro.md"
				data-separator="^-----\n"
				data-separator-vertical="^---\n"
				data-separator-note="^Note:"
				data-charset="utf-8">
	</section>
	<section data-markdown="markdown/webservices.md"
				data-separator="^-----\n"
				data-separator-vertical="^---\n"
				data-separator-note="^Note:"
				data-charset="utf-8">
	</section>

...

Aussehen würde eine beispielhafte Slideabfolge einer Sektion dabei wie folgt:

## OpenAPI

aka Swagger

Note:
* maschinenlesbare Interfacedefinitionen
* Contract-First-Gedanke
* betreut von der OpenAPI Initative

---

![OpenAPI Initiative](images/openapi.png)

Note:
* Atlassian
* Google
* Paypal
* SAP

...

Damit lassen sich über Markdown schnell Präsentationen erzeugen, welche den Fokus auf den Inhalt, anstelle der mühsamen Gestaltung legen.

Schreiben

Neben den vorgestellten Texteditoren, existieren eine Reihe von Werkzeugen, welche sich auf den Aspekt des Schreibens längerer Werke, mittels Markdown konzentrieren.

So existiert mit iA Writer ein minimalistischer Texteditor, der sich besonders an Autoren, Journalisten und andere Schreibende richtet, die eine ablenkungsfreie Umgebung schätzen.

Speziell zu iA Writer existieren Open Source-Alternativen, wie FocusWriter, welche sich ebenfalls ablenkungsfreies Schreiben auf die Fahnen geschrieben haben.

Ulysses

Eine weitere auf Markdown zentrierte Schreibanwendung ist Ulysses, die speziell für Autoren und Schriftsteller entwickelt wurde. Sie bietet eine ablenkungsfreie Benutzeroberfläche und eine Vielzahl von Werkzeugen, die das Schreiben und Organisieren von Texten erleichtern.

Ulysses unter macOS

Die App basiert auf Markdown, und die erzeugten Dokumente können in unterschiedliche Ausgabeformate exportiert werden.

Kollaboratives Schreiben

Neben dem Schreiben als Einzelperson existieren etliche Werkzeuge für kollaboratives Schreiben, wie zum Beispiel die unterschiedlichsten Varianten von EtherPad. Mit HedgeDoc existiert ein solcher webbasierter Editor mit Markdown-Unterstützung.

HedgeDoc als kollaborativer Markdown-Editor

Ursprünglich als CodiMD bekannt, bietet die Anwendung eine benutzerfreundliche Oberfläche, die sowohl für Einzelpersonen als auch für Teams geeignet ist. Die Markdown-Unterstützung orientiert sich an CommonMark und dem GitHub Flavored Markdown.

Zettlr

Zettlr ist eine freie Software, die darauf abzielt, das Schreiben und Verwalten von Texten zu unterstützen. Hier liegt der Fokus auf wissenschaftlichem Arbeiten. Die Anwendung bietet Funktionen zur Erstellung von Markdown-Dokumenten und zur Organisation von Notizen.

Zettlr unter macOS

Zudem ist sie mit Referenzverwaltungstools wie Zotero kompatibel, was die Verwaltung von Literaturquellen erleichtert. Zettlr ermöglicht den Export von Dokumenten in verschiedene Formate wie PDF und Word.

Im weiten Web

Grundsätzlich findet sich Markdown-Unterstützung in vielen webbasierten Systemen, wie Wikis, Diskussionsplattformen und vielen weiteren.

Foren wie Reddit und Stack Overflow unterstützen Markdown, um Benutzern das Formatieren ihrer Beiträge zu erleichtern. Durch die einfache Syntax können auch Nutzer ohne größere technische Vorkenntnisse ihre Beiträge sinnvoll gestalten.

Konverter

Neben dem Schreiben in Markdown ist oft auch der Export in andere Formate gewünscht. Während viele Applikationen dies von sich aus beherrschen, gibt es auch spezialisierte Software wie Pandoc, für solche Zwecke.

Pandoc ist ein Werkzeug zur Konvertierung von Dokumenten zwischen verschiedenen Formaten. Es unterstützt die Konvertierung von Markdown in HTML, PDF, DOCX, LaTeX und viele andere Formate.

Pandoc nutzt hierbei seinen eigenen Markdown-Dialekt und ist freie Software.

Ressourcen und Dokumentation

Neben Dokumenten wie der ursprünglichen Spezifikation und CommonMark existieren es eine Reihe von Ressourcen, die in Markdown einführen, wie der Markdown Guide.

Dieser bietet eine umfangreiche Ressource rund um Markdown, führt in die Syntax ein und pflegt eine Liste von Markdown-Tooling.

Auch existieren unzählige Cheat Sheets und Tutorials für Markdown und ermöglichen es Einsteigern schnell in der Markdown-Welt anzukommen.

Fazit

Markdown wurde ursprünglich mit einem minimalistischen Ansatz entwickelt und hat sich schnell eine breite Anhängerschaft aufgebaut. Während die unterschiedlichen Varianten etwas Verwirrung stiften können, ist der Kern von Markdown wohl definiert.

Selbst ohne spezielle Tools lässt sich Markdown problemlos lesen und verstehen, was es ideal für die Erstellung von Dokumentationen, Notizen und Texten macht.

Mittels Markdown können elegant und schnell Texte geschrieben werden, ohne dass sich in Formatierungsoptionen und Designfragen verloren wird. Damit bietet es im Zusammenhang mit entsprechenden Applikationen eine ablenkungsfreie und effiziente Schreibumgebung.

Überdies bietet Markdown bzw. die Werkzeuge rund um Markdown die Flexibilität, ansprechend formatierte Dokumente zu exportieren. Diese Kombination aus Einfachheit und Vielseitigkeit machte Markdown zu einem unverzichtbaren Werkzeug.

Neben dem reinen Schreiben hat sich Markdown darüber hinaus viele weitere Anwendungsgebiete erobert und wird uns sicherlich auch in Zukunft begleiten.

Dieser Artikel erschien ursprünglich auf Golem.de und ist hier in einer alternativen Variante zu finden.

Reguläre Ausdrücke

Richard Feynman, einer der bekanntesten Physiker des 20. Jahrhunderts, war überzeugt, dass niemand die Quantentheorie versteht. Über reguläre Ausdrücke, auch reguläre Expressionen genannt, könnte ähnliches behauptet werden. Vielleicht liegt es daran, dass diese Ausdrücke auf den ersten Blick einschüchternd aussehen können:

#?([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})

Allerdings sind reguläre Ausdrücke nicht ganz so kontraintuitiv wie besagte Theorie und sind in der Entwicklung sowie im IT-Alltag ein Werkzeug, welches in vielen Fällen hilfreich zur Seite stehen kann, aber auch Grenzen hat.

Definition

Aus Sicht der theoretischen Informatik ist ein regulärer Ausdruck eine Methode, um Mengen von Zeichenketten mit gemeinsamen Mustern zu beschreiben. Reguläre Ausdrücke werden durch die Verwendung von verschiedenen Operatoren und Konventionen definiert, die es ermöglichen, komplexe Suchmuster zu erstellen.

Die Theorie der regulären Ausdrücke basiert auf den Konzepten der endlichen Automaten und der regulären Sprachen. Vereinfacht gesehen, kann die Funktionalität eines regulären Ausdrucks als Musterabgleich gesehen werden. Oft werden diese Ausdrücke als Regex oder Rexexp abgekürzt.

Ein einfacher regulärer Ausdruck könnte wie folgt aussehen:

[abc]

Dieser Ausdruck würde in einem Text die Zeichen a, b, und c finden. Über einen solchen regulären Ausdruck können Zeichenfolgen in Texten identifiziert, extrahiert und verarbeitet werden.

Geschichte

Die Geschichte regulärer Ausdrücke geht zurück auf das Jahr 1951, in welchem der Mathematiker Stephen Cole Kleene den Begriff prägte.

Praktische Anwendung fanden solche Ausdrücke in den 1960er-Jahren, als Ken Thompson, diese im Editor QED implementierte, als er diesen für das Compatible Time-Sharing System (CTSS) neuschrieb.

Über die Jahre wurde die Funktionalität regulärer Ausdrücke in weitere Werkzeuge wie grep und sed integriert. Im Rahmen der Unix-Philosophie, in welcher ein Werkzeug eine Aufgabe gut beherrschen soll, boten sich hiermit noch mächtigere Werkzeuge für die Textverarbeitung. Die Ausdrücke fanden nicht nur in der Textverarbeitung, sondern auch in der lexikalischen Analyse im Compiler-Design Anwendung.

Neben der Integration in solche Werkzeuge wurde vor allem beginnend mit den 1980er-Jahren die Integration regulärer Ausdrücke in Programmiersprachen wie Perl vorangetrieben. Einhergehend mit dieser Entwicklung wurde die Ausdrücke mächtiger und mehr Anwendungsfälle konnten mit diesen bearbeitet werden. Larry Wall, der Schöpfer von Perl, erweiterte die Fähigkeiten regulärer Ausdrücke erheblich und machte sie zu einem zentralen Bestandteil seiner Sprache.

In den 1990er-Jahren kam es zu einer Standardisierung von Syntax und Verhalten regulärer Ausdrücke, was die Entwicklung der Bibliothek der Perl-kompatiblen regulären Ausdrücke (PCRE) vorantrieb. Diese Bibliothek wurde in vielen Anwendungen verwendet und ist bis heute eine der am weitesten verbreiteten Implementierungen von regulären Ausdrücken.

Grundlagen

Doch wie genau werden reguläre Ausdrücke erstellt? Solche Ausdrücke können aus vielen unterschiedlichen Elementen bestehen, wie Literalen, Zeichenklassen, Quantifizierer und Gruppen.

So wäre ein regulärer Ausdruck bestehend aus einem einzigen Literal gültig:

a

Dieser Ausdruck würde hierbei auf die Vorkommen von a in einem Text matchen.
In regulären Ausdrücken können Oder-Verknüpfungen gebildet werden. So würde der Ausdruck:

a|b

entweder auf das Zeichen a oder auf das Zeichen b in einem Text matchen.

In den meisten Fällen wird allerdings nicht nach einem einzelnen Literal gematcht, sondern mit Zeichenklassen, Quantifizierern und Gruppen gearbeitet. Im Grundsatz würde allerdings nichts dagegen sprechen, einen regulären Ausdruck komplett, als Literal zu definieren:

Supercalifragilisticexpialigetisch

Diese Definition würde dazu führen, dass jedes Auftreten des Wortes Supercalifragilisticexpialigetisch gematcht werden würde. Allerdings wäre der reguläre Ausdruck in diesem Fall nicht mehr als eine einfache Suche.

Da es in regulären Ausdrücken eine Reihe von Zeichen mit spezieller Bedeutung gibt, müssen diese in bestimmten Fällen maskiert werden. Dies geschieht mit einem Backslash und dem sich anschließenden Zeichen:

\.

In diesem Beispiel würde der Punkt als normaler Punkt behandelt werden und nicht als Zeichen mit spezieller Bedeutung betrachtet werden.

Zeichenklassen

Zeichenklassen in regulären Ausdrücken erlauben es, eine Menge von Zeichen zu definieren, von denen jedes ein potenzielles Match für ein Zeichen aus dem Eingabetext darstellen kann. So würde der reguläre Ausdruck:

[abcdefghijklmnopqrstuvwxyz]

auf alle Zeichen zwischen a und z matchen. Die Zeichen werden hierbei in eckige Klammern eingefasst. Obiger Ausdruck kann allerdings sinnvoller gestaltet werden:

[a-z]

Der Bindestrich führt dazu, dass der Ausdruck als a bis z gelesen werden kann und damit einen Bereich definiert. Auch können mehrere Zeichenklassen in einem Block definiert werden:

[a-zA-Z]

Diese Zeichenklassen würde bei Buchstaben in Klein- und Großschreibung anschlagen. Bei dieser Notation ist darauf zu achten, dass die Definitionen ohne Leerzeichen aneinander gehangen werden.

Um auch deutsche Umlaute und das Eszett zu berücksichtigen, müssen diese Zeichen explizit zur Zeichenklasse hinzugefügt werden:

[a-zA-ZäöüÄÖÜß]

Standard-Zeichenklassen

Neben den selbstdefinierten Zeichenklassen existieren eine Reihe von vordefinierten Zeichenklassen, welche ebenfalls genutzt werden können.

So existiert die Zeichenklasse \d, welche allen Dezimalziffern entspricht, also 0 bis 9; dies entspricht der selbstdefinierten Zeichenklasse:

[0-9]

Die Zeichenklasse \D definiert das Gegenteil der vorherigen Klasse und matcht auf alle Nichtziffern und entspricht damit folgender Zeichenklasse:

[^0-9]

Während der Zirkumflex innerhalb einer Zeichenklasse normal genutzt werden kann, negiert er, am Anfang der Zeichenklasse stehend, diese. Eine Erweiterung dieser Standardklassen sind die Klassen \w und \W, welche für alle Wortzeichen stehen und folgenden selbstdefinierten Zeichenklassen entsprechen würden:

[a-zA-Z0-9_]
[^a-zA-Z0-9_]

Daneben existieren, abhängig von der Implementierung weitere vordefinierte Zeichenklassen, wie \s für Whitespace-Zeichen oder die Klasse \S für alle Nicht-Whitespace-Zeichen.

Metazeichen

Im Rahmen regulärer Ausdrücke sind einige Metazeichen definiert, welche unterschiedlichste Bedeutungen haben und nicht als die Zeichen selbst interpretiert werden. Sie werden verwendet, um Muster für die Textsuche und -manipulation zu definieren. Einige dieser Zeichen sollen nachfolgend vorgestellt werden.

Der Punkt ist als Metazeichen so definiert, dass er für jedes beliebige Zeichen, bis auf einen Zeilenumbruch steht. Damit würde der Ausdruck:

a.c

unter anderem auf folgende Zeichenketten matchen:

aac
abc
acc

Solange ein a gefolgt von einem beliebigen Zeichen, wiederum gefolgt von einem c im Text vorkommt, wird dieses gematcht.

Der Zirkumflex markiert den Anfang einer Zeile bzw. eines Textes. Damit würde der reguläre Ausdruck:

^Lorem Ipsum

in einem gegebenen Beispieltext:

Lorem Ipsum
	
abcdefghijklmnopqrstuvwxyz ABCDEFGHIKLMNOPQRSTUWXYZ
	
Lorem Ipsum

das Auftreten von Lorem Ipsum am Anfang des Textes matchen. Die gegenteilige Operation kann mit dem Metazeichen $ erreicht werden:

Lorem Ipsum$

In diesem Fall würde das Lorem Ipsum am Ende des Beispieltextes gefunden werden.

Es ist wichtig zu beachten, dass innerhalb einer benutzerdefinierten Zeichenklasse die meisten Metazeichen, wie der Punkt oder der Stern, ihre spezielle Bedeutung verlieren und als normale Zeichen behandelt werden. Ausnahmen sind der Zirkumflex, wenn er als erstes Zeichen in der Klasse verwendet wird, um die Klasse zu negieren, der Bindestrich, um einen Bereich anzugeben, und der Backslash, um Escape-Sequenzen zu ermöglichen.

Quantifizierer

Quantifizierer (engl. Quantifiers) in regulären Ausdrücken sind spezielle Metazeichen, die angeben, wie oft das vorangehende Element in einem Textmuster vorkommen muss, um eine Übereinstimmung zu erzielen. Sie sind entscheidend, um die Flexibilität der Mustererkennung zu erhöhen.

Gegeben sei folgende Telefonnummer:

0176/04069015

Für diese Nummer könnte ein regulärer Ausdruck erstellt werden:

[0-9][0-9][0-9][0-9]/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]

In dem Beispiel wurde auf Standardzeichenklassen verzichtet. Stattdessen wurden eigene Zeichenklassen definiert. Durch diesen Ausdruck werden die ersten vier Ziffern, dann ein Slash und anschließend die folgenden Ziffern gematcht.

Allerdings ist dieser Ausdruck weder sonderlich elegant, noch deckt er das Problem vollständig ab. Immerhin können Telefonnummern unterschiedlich lang sein und auch der Slash könnte optional sein. Hier kommen Quantifizierer zum Einsatz, von denen es eine Vielzahl mit diversen Anwendungsoptionen gibt.

Der Stern-Quantifizierer definiert, dass das vorangehende Element null- oder mehrmals vorkommt. So würde der Ausdruck:

a*b

unter anderem auf folgende Zeichenketten matchen:

ab
aab
aaab
b

Die Anzahl der a’s vor dem Zeichen b sind hierbei unerheblich.

Das Plus-Quantifizierer definiert, dass das vorangehende Element mindestens einmal vorkommen muss. Damit würde der Ausdruck:

a+b

unter anderem auf folgende Zeichenketten matchen:

ab
aab
aaab

Ein Match auf eine Zeichenkette nur bestehend aus einem b wäre bei diesem Quantifizierer ausgeschlossen.

Zu dieser Gruppe von Quantifizierern gehört auch das Fragezeichen. Bei diesem kann das vorangehende Element null- oder einmal vorkommen. Damit würde der Ausdruck:

a?b

unter anderem auf folgende Zeichenketten matchen:

ab
b

Ein Match auf eine Zeichenkette wie aab wäre bei dieser Variante ausgeschlossen.

Daneben existieren eine Reihe von komplexeren Quantifizierer wie den geschweiften Klammern, mit denen eine bestimmte Anzahl von Wiederholungen definiert werden kann. Der Ausdruck:

a{3}b

wurde spezifizieren, dass drei a’s hintereinander folgend von einem b gesucht werden. Damit würde dieser Ausdruck auf folgende Zeichenkette matchen:

aaab

Eine Erweiterung dieser Variante ist die Nutzung von Bereichen:

a{2,4}b

Hiermit würden alle Zeichenketten matchen bei denen zwischen zwei und vier a’s enthalten sind:

aab
aaab
aaaab

Eine weitere Abwandlung dieser Notationen ist es festzulegen, wie oft ein Element mindestens vorkommen muss:

a{2,}b

In diesem Fall müsste das Zeichen a mindestens zweimal vorkommen.

Mithilfe dieser Quantifizierer könnte der Ausdruck zum Match obiger Telefonnummer nun wesentlich vereinfacht werden:

[0-9]+/?[0-9]+

Damit ist der Ausdruck so definiert, dass eine beliebige Anzahl an Ziffern vorkommen können, gefolgt von einem optionalen Slash, wiederum gefolgt von einer beliebigen Anzahl an Ziffern.

Allerdings zeigt sich hier auch eine der Grenzen regulärer Ausdrücke: die Vielfalt möglicher Telefonnummernformate weltweit. Je nach Land und Region gelten unterschiedliche Regeln für den Aufbau einer Telefonnummer. Ein umfassender regulärer Ausdruck, der all diese Varianten abdeckt, könnte schnell sehr komplex werden und schwer zu warten sein.

In solchen Fällen kann es sinnvoll sein, zusätzliche Validierungslogik zu implementieren und nicht zu versuchen, die komplette Logik über einen regulären Ausdruck zu implementieren.

Gierige und faule Quantifizierer

Bei den beschriebenen Quantifizierern existieren gierige (engl. greedy) und faule (engl. lazy) Varianten. Gierige Quantifizierer versuchen, so viel wie möglich von der Zeichenkette zu erfassen, während sie den Regeln des regulären Ausdrucks folgen. Damit greifen sie den längstmöglichen Teil der Zeichenkette, der mit dem Muster übereinstimmt.

Faulen Quantifizierern hingegen geht es darum, so wenig wie möglich zu erfassen, während sie immer noch eine Übereinstimmung finden. Damit greifen sie den kürzestmöglichen Teil der Zeichenkette, der mit dem Muster übereinstimmt.

Quantifizierer sind im Normalfall gierig. Der Ausdruck:

a.*b

würde hiermit die Zeichenfolge:

ababab

als Ganzes matchen. Um diesen Ausdruck in der Lazy-Konfiguration zu betreiben, muss ein Fragezeichen nachgestellt werden:

a.*?b

In diesem Fall würden die ab-Blöcke jeweils einzeln gematcht werden.

Neben diesen beiden Varianten existieren noch possessive Quantifizierer. Solche Quantifizierer verhalten sich wie gierige Quantifizierer, aber sie geben einmal erfasste Zeichen nicht mehr frei.

Das kann das Matching verhindern, wenn der Rest des Musters nicht mehr passt. Possessive Quantifizierer können in bestimmten Situationen die Effizienz der Auswertung verbessern, da sie das aufwendige Backtracking unterbinden, können aber auch zu nicht intuitiven Ergebnissen führen, wenn sie nicht mit Bedacht eingesetzt werden.

Gruppierungen

Eine weitere Möglichkeit bei der Entwicklung regulärer Ausdrücke sind Gruppierungen. So würde der Ausdruck:

abc

nur auf die Zeichenkette abc matchen. Sollen hier jetzt auch Zeichenketten wie abcabc gematcht werden, können Klammern zur Gruppierung im Zusammenhang mit einem Quantifizierer genutzt werden:

(abc)+

Damit würden unter anderem folgende Zeichenketten auf den Ausdruck passen:

abc
abcabc
abcabcabc

Eine weitere Art von Gruppierung ist die Bildung von sogenannten Erfassungsgruppen. Mit diesen Gruppen, welche einen Teil des Ausdrucks ausmachen, kann später weitergearbeitet werden, z. B. in Form von Rückreferenzen:

(abc).*\1

In diesem Beispiel wird die Zeichenkette abc gesucht, welcher beliebige Zeichen folgen, bis schlussendlich wieder abc folgt. Dies wird über den Rückverweis auf die erste Erfassungsgruppe (\1) gelöst. Damit würde dieser Ausdruck unter anderem auf folgende Zeichenketten matchen:

abcabc
abcloremabc
abcipsumabc

Eine weitere Möglichkeit zur Nutzung von Gruppierung sind Oder-Verknüpfungen in einer Gruppe:

(a|b)c

Mit einer solchen Verknüpfung würden Zeichenketten wie ac und bc gematcht, allerdings nicht die Zeichenkette abc.

Daneben existieren Varianten wie verschachtelte Gruppen, benannte Gruppen oder nicht erfassende Gruppen, welche hier nicht weiter im Detail behandelt werden sollen.

Lookaround-Assertions

Eine weitere Möglichkeit zur Verfeinerung von regulären Ausdrücken sind Lookahead– und Lookbehind-Assertions. Im Deutschen könnte man diese Begrifflichkeiten mit vorwärts bzw. rückwärtsgerichtete Bedingungen grob übersetzen. Mit diesen kann die Umgebung eines Matches definiert werden.

So würde der Ausdruck:

Redaktion(?=skonferenz)

in einem Text auf das Wort Redaktion matchen, wenn es in der Zeichenkette Redaktionskonferenz enthalten wäre. Würde das Wort Redaktion alleine im Text stehen, so würde hier kein Match stattfinden. Bei dieser Variante handelt es sich um einen positiven Lookahead, da überprüft wird, ob das Muster nach dem Match vorkommt.

Das Gegenteil ist ein negativer Lookahead:

Redaktion(?!skonferenz)

Bei diesem würde auf das einzelne Wort Redaktion gematcht werden, auf das Wort Redaktion in der Zeichenkette Redaktionskonferenz allerdings nicht.

Neben den Lookahead-Assertions existieren analog dazu Lookbehind-Assertions welche prüfen, ob das Muster vor dem Match vorhanden ist:

(?<=Schluss)redaktion
(?<!Schluss)redaktion

Ein komplexeres Beispiel für die Anwendung von Lookarounds könnte die Suche nach verschiedenen Schreibweisen des Wortes Hauptstraße sein. Ein regulärer Ausdruck, der Hauptstr., Hauptstraße und Hauptstrasse matcht, könnte wie folgt aussehen:

Hauptstr(aße|asse|\.)(?=\s|\b)

Hierbei sorgt die Lookahead-Assertion (?=\s|\b) dafür, dass das Match nur dann stattfindet, wenn das gesuchte Wort gefolgt von einem Whitespace (\s) oder einem Wortgrenzenzeichen (\b) steht. Diese Vorgehensweise verhindert, dass unerwünschte Matches wie Hauptstrasseneinmündung entstehen.

Flags

Neben den eigentlichen regulären Ausdrücken existieren eine Reihe von Optionen, welche das Verhalten der Engine zur Auswertung der regulären Ausdrücke anpassen.

So existiert mit der Global-Option (g) die Möglichkeit die Suche im gesamten Text durchzuführen und nicht nur bis zur ersten Übereinstimmung. Mit der Option i ignoriert die Engine die Groß- und Kleinschreibung im Rahmen der Mustererkennung.

Die Option Multiline (m) verändert das Verhalten für die Zeichen ^ und $, sodass sie nicht mehr nur den Start und das Ende des gesamten Textes markieren, sondern den Anfang und das Ende jeder einzelnen Zeile analysieren. Über die Singleline– bzw. Dotall-Direktive (s) kann der Punkt als Wildcard-Zeichen auch über die Grenzen der Zeilenumbrüche hinweg arbeiten.

Mit der Unicode-Option (u) kann bei einigen Engines die Auswertung von Unicode-Zeichen aktiviert werden.

Gesetzt werden können diese Flags als Teil des regulären Ausdrucks, so z. B. für das Global-Flag in Verbindung mit der Ignorierung der Groß- und Kleinschreibung:

(abc)/gi

Je nach verwendeter Engine werden diese Flags auch anders gesetzt, z. B. in Java beim Anlegen eines Pattern:

Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(text);

Daneben existieren in einigen Engines bestimmte Flags nicht, z. B. da Java bereits so konzipiert ist, dass die Engine alle Übereinstimmungen in einem gegebenen Text finden kann. Damit entspricht dieses Verhalten dem Global-Flag.

Unterschiede

Obwohl die grundlegenden Konzepte von regulären Ausdrücken über verschiedene Sprachen hinweg ähnlich sind, gibt es Unterschiede in der Syntax und Funktionalität, die Entwickler beachten müssen.

Einige Engines bieten erweiterte Funktionen wie Lookahead– und Lookbehind-Assertions, andere unterstützen benannte Gruppen. Die Unterstützung für Unicode ist ebenfalls ein Unterscheidungsmerkmal, da manche Engines in der Lage sind, mit einer Vielzahl von Zeichensätzen und Sprachen umzugehen, während andere auf ASCII beschränkt sind.

Trotz der Vielfalt unter den Engines haben sich viele Gemeinsamkeiten herausgebildet. Dazu gehören Metazeichen wie den Punkt für jedes Zeichen, den Stern für null oder mehr Wiederholungen, das Plus für eine oder mehr Wiederholungen und das Fragezeichen für null oder eine Wiederholung. Ebenso sind Zeichenklassen, Negationen, Anker für Anfang und Ende einer Zeichenkette, und einfache Quantifizierer weitgehend identisch.

Reguläre Ausdrücke in der Entwicklung

Bei der Anwendung regulärer Ausdrücke in der Entwicklung sind die jeweiligen Gegebenheiten der Programmiersprachen zu berücksichtigen. Ein Beispiel hierfür ist die Java-Methode zum Matchen in der Stringklasse:

String text = "3";
boolean matches = text.matches("[123]");

Hier wird die matches-Methode genutzt, um zu überprüfen, ob der gesamte String text dem regulären Ausdruck entspricht. Diese Herangehensweise ist für einmalige Überprüfungen einfach und direkt. Allerdings ist es ineffizient, wenn der gleiche Ausdruck in einer Schleife oder mehrfach im Code verwendet wird, da bei jedem Aufruf der Ausdruck neu kompiliert wird.

Alternativ kann diese Operation anders implementiert werden:

Pattern pattern = Pattern.compile("[123]");
boolean matches = pattern.matcher(text).matches();

Diese Variante ist effizienter, wenn der gleiche Ausdruck mehrfach genutzt werden soll. Hier wird das Pattern einmal kompiliert und kann anschließend mehrfach verwendet werden, ohne dass es jedes Mal neu kompiliert werden muss.

Reguläre Ausdrücke in Anwendungen

Neben der direkten Nutzung regulärer Ausdrücke in der Entwicklung, existieren unzählige Tools, wie Texteditoren oder Kommandozeilenwerkzeuge wie grep, welche ebenfalls Unterstützung für reguläre Ausdrücke liefern.

Für grep könnte dies wie folgt aussehen:

grep -E "G{1}N" gpl3.txt

Auch Texteditioren und IDEs enthalten Suchmethodiken, um über reguläre Ausdrücke zu finden.

Die Suche mittels regulärer Ausdrücke in IntelliJ IDEA

Damit ist es möglich, Textstellen zu finden, die komplexeren Mustern entsprechen und mit einer einfachen Suche nicht ohne weiteres gefunden werden können.

Nutzung

Reguläre Ausdrücke sind ein mächtiges Werkzeug, wenn es darum geht, Benutzereingaben zu validieren. Sie werden häufig verwendet, um sicherzustellen, dass E-Mail-Adressen, Telefonnummern und andere Formen von Daten bestimmten Mustern entsprechen.

So könnte mit einem solchen Ausdruck z. B. die Validität einer E-Mail-Adresse überprüft werden:

[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?

Daneben können sie beim Parsen von Zeichenketten genutzt werden, z. B. um spezifische Informationen aus einem Text wie einer Logdatei herauszufiltern.

In der Compiler-Konstruktion werden reguläre Ausdrücke verwendet, um Tokens zu identifizieren, indem sie Muster definieren, die Schlüsselwörter, Operatoren oder andere syntaktische Elemente erkennen. Auch bei der Textbearbeitung, wie dem massenhaften Ersetzen, können reguläre Ausdrücke ihre Stärke ausspielen.

Trotzdem sollte nicht vergessen werden, dass sich reguläre Ausdrücke nicht für alle Zwecke eignen. So sollte z. B. davon abgesehen werden, nicht formale Sprachen mit regulären Ausdrücken zu parsen. Für das Parsen von HTML mittels regulärer Ausdrücke existiert dazu ein geradezu legendärer Post bei Stack Overflow, der sich dieses Problems annimmt.

Stack Overflow beantwortet die Frage nach dem Sinn von regulären Ausdrücken in Verbindung mit HTML

Best Practices

Werden reguläre Ausdrücke genutzt, so sollten einige Best Practices berücksichtigt werden. Bei unsachgemäßer Verwendung kann ein regulärer Ausdruck schnell unübersichtlich und schwer wartbar werden kann.

So sollten genutzte reguläre Ausdrücke kommentiert werden und ihre Fachlichkeit darlegen, um das Verständnis zu erhöhen.

Anstelle von nummerierten Rückreferenzen lassen sich, wenn unterstützt, benannte Gruppen nutzen. Einige Engines erlauben auch die Verwendung von Leerzeichen und Zeilenumbrüchen in den Ausdrücken, was hilft, sie besser zu strukturieren. Zudem kann es vorteilhaft sein, lange und komplexe Muster in kleinere, wiederverwendbare Teile zu zerlegen, was die Wartung und das Verständnis des Ausdrucks erleichtert.

Es ist ratsam, in regulären Ausdrücken so spezifisch wie möglich zu sein. Anstatt generische Zeichen wie den Punkt, der jedes Zeichen repräsentieren kann, zu verwenden, sollten präzisere Zeichen oder Zeichenklassen gewählt werden. Dies hilft, unnötiges Backtracking zu vermeiden, das die Performance beeinträchtigen kann.

Obwohl Lookaround-Assertions in bestimmten Situationen sehr nützlich sein können, sollten sie mit Bedacht eingesetzt werden, da sie bei komplexen Mustern und großen Textmengen die Performance negativ beeinflussen können. Auch bei der Verwendung von Gruppierungen gilt gleiches, denn jede zusätzliche Gruppierung bedeutet mehr Aufwand bei der Verarbeitung des Ausdrucks.

Schließlich ist es unerlässlich, dass reguläre Ausdrücke gründlich getestet werden. Idealerweise sollte dies mit einer breiten Palette von Testfällen geschehen, um sicherzustellen, dass sie in jeder erwarteten Situation korrekt funktionieren.

Unter der Haube

In der alltäglichen Anwendung werden regulären Ausdrücke von einer Engine ausgeführt. Ein kurzer Blick in eine solche Engine, kann sich lohnen, da es hilft zu verstehen, wie reguläre Ausdrücke sinnvoll gestaltet werden können. Eine Engine, die diese Ausdrücke verarbeitet, kann entweder textorientiert oder regex-orientiert sein.

Eine textorientierte Engine, implementiert als deterministischer endlicher Automat (DFA), analysiert den Eingabetext sequenziell. Diese Methode ist schnell und effizient, da sie keine alternativen Pfade verfolgt und somit kein Backtracking benötigt. DFAs liefern stets die längste Übereinstimmung und sind aufgrund ihrer deterministischen Natur in der Performance vorhersehbar.

Im Gegensatz dazu steht die regex-orientierte Engine, die auf einem nichtdeterministischen endlichen Automaten (NFA) basiert. Eine solche Engine ist in der Lage, mehrere Pfade gleichzeitig zu verfolgen und bei Bedarf mittels Backtracking alternative Wege zu untersuchen. Dies ermöglicht eine flexible Mustererkennung, kann jedoch bei komplexen Ausdrücken zu einer erhöhten Rechenlast führen. NFAs priorisieren die am weitesten links stehende Übereinstimmung und können bei mehreren möglichen Matches zu einer kürzeren Übereinstimmung führen, selbst wenn weiter rechts im Text eine längere vorhanden wäre.

Moderne Regex-Engines sind meist regex-orientiert und nutzen einen Preprozessor, um den regulären Ausdruck vorzuverarbeiten, etwa um Makros in Zeichenklassen umzuwandeln. Anschließend wird der Ausdruck kompiliert, wobei er in eine effiziente Form überführt wird, die entweder als Reihe von Instruktionen oder als Zustandsautomat von der Engine verarbeitet werden kann.

Die Wahl der Engine hängt von den spezifischen Anforderungen der Aufgabe ab. Während DFAs für einfache, vorhersehbare Suchvorgänge geeignet sind, bieten NFAs die notwendige Flexibilität für komplexere Mustererkennungen.

Risiken und Nebenwirkungen

Neben der Möglichkeit reguläre Ausdrücke für Aufgaben zu nutzen, für die sie nicht geeignet sind, existieren auch andere Probleme, die mit diesen Ausdrücken zusammenhängen.

So gibt es den Regular expression Denial of Service
-Angriff (ReDoS), welcher ausnutzt, dass viele Engines für reguläre Ausdrücke bei bestimmten Ausdrücken extrem langsam werden und viele Systemressourcen beanspruchen können.

Ein schönes Beispiel für eine solche Anfälligkeit, war der Ausfall von Stack Overflow im Jahre 2016. Dieser wurde durch einen Post mit zu vielen Leerzeichen verursacht, welcher dazu führte, dass die auf Backtracking basierte Engine über 199 Millionen Überprüfungen durchführen musste.

Allerdings gibt es Alternativen zu Backtracking nutzenden Engines, wie RE2 von Google. Diese Engine garantiert, basierend auf einem endlichen Automaten, eine lineare Ausführungszeit, bezogen auf die Eingabedaten und ist trotzdem mit den Features moderner Engines ausgestattet.

Werkzeuge

Für die Nutzung und Erstellung von regulären Ausdrücken existieren hilfreiche Werkzeugen. Zu diesen Werkzeugen gehören eine Reihe von Online-Testern. Dies sind interaktive Werkzeuge, die es dem Nutzer ermöglicht, regulären Ausdrücke in Echtzeit zu testen und zu debuggen. Diese Werkzeuge bieten oft farblich hervorgehobene Übereinstimmungen und Erklärungen für jedes Element des Ausdrucks.

Einer dieser Tester ist RegExr, welcher unter regexr.com zu finden ist.

Mit RegExr können reguläre Ausdrücke schnell ausprobiert werden

Neben der interaktiven Oberfläche bietet RegExr eine Referenz und eine große Anzahl von Community Patterns, die viele Probleme bereits abdecken und so die Entwicklung eines eigenen Ausdrucks beschleunigen können.

Ein weiterer Tester für reguläre Ausdrücke ist regular expressions 101, welcher unter regex101.com zu finden ist.

regular expressions 101 verfügt über einen Debugger

Eine Besonderheit dieses Dienstes ist der integrierte Debugger, mit welchem regulären Ausdrücke analysiert werden können. Einen umgekehrten Weg geht der Regex Generator von Olaf Neumann.

Der Regex Generator von Olaf Neumann

Mithilfe dieses Werkzeuges können reguläre Ausdrücke anhand eines Datenbeispieles erzeugt werden. Kommandozeilenwerkzeuge wie rgxg arbeiten nach ähnlichen Prinzipien und können auch offline genutzt werden.

Fazit

Insgesamt sind reguläre Ausdrücke ein mächtiges Werkzeug, um Textmuster zu durchsuchen und zu manipulieren. Sie ermöglichen eine effiziente Verarbeitung von Texten und sind daher ein wichtiges Werkzeug für Entwickler und Anwender. In der Praxis werden sie in verschiedenen Bereichen eingesetzt, um Texte zu durchsuchen, zu filtern und zu manipulieren.

Durch die Einhaltung von Best Practices und dem damit verbundenen Vermeiden häufiger Fehler können Entwickler sicherstellen, dass ihre regulären Ausdrücke sowohl leistungsfähig als auch wartbar sind.

Dieser Artikel erschien ursprünglich auf Golem.de und ist hier in einer alternativen Variante zu finden.