Markdown entfernen: was der Klartext verliert und was eine Regex falsch macht
Veröffentlicht am 3.6.2025 · 11 Min. Lesezeit · Text- & Sprach-Tools
Daniel Okonkwo — Front-end-Entwickler und Tech-Redakteur bei Allin
Web-Performance · Dateiformate
Anhand von 5 Quellen geprüft
Markdown trägt Bedeutung in seiner Zeichensetzung, das Löschen der Syntax löscht also Information. Lass einen naiven Entferner über einen kurzen Bericht laufen, und die Verluste sind konkret: [vollständige Aufschlüsselung](https://example.com/q3.pdf) wird zu vollständige Aufschlüsselung, und das Ziel ist fort, ohne jede Spur, dass je ein Link da war; eine zweistufige Liste aus Regionen und Kanälen kommt linksbündig heraus, sodass Laden: +4 % und Laden: unverändert zu keiner Region mehr gehören; und eine Tabelle wird zu einer Reihe von Wörtern, deren Trennzeile aus Bindestrichen als wörtlicher Text überlebt. Darunter liegt ein zweites Problem: Markdown hat keine einzige Spezifikation. CommonMark und GitHub Flavored Markdown weichen voneinander ab - eine Tabelle mit senkrechten Strichen, ~~Durchstreichung~~, eine nackte URL und eine Aufgabenliste sind GFM-Erweiterungen und bleiben unter CommonMark wörtlicher Text -, und ein Regex-Entferner macht zusätzlich Fälle falsch, die ein Parser richtig macht. In Node überprüft: Ein naiver Entferner macht aus bericht_final_v2.txt den Namen berichtfinalv2.txt und aus 2 * 3 * 4 die Folge 2 3 4, und er verändert das Innere eines eingezäunten Codeblocks, während ein CommonMark-Parser alle drei unangetastet lässt. Behalte den Linktext samt Ziel in Klammern, behalte Listenzeichen als Aufzählungspunkte und Codeblock-Inhalte wortwörtlich; wirf Hervorhebungszeichen und Überschriften-Rauten weg.
Ein Link wird zu Text, dessen Ziel gelöscht ist, eine verschachtelte Liste verliert ihre Hierarchie, eine Tabelle wird zu einer Reihe von Wörtern. Dann die technische Hälfte: Markdown hat keine einzige Spezifikation, und ein Regex-Entferner verstümmelt einen Dateinamen, ein Malzeichen und das Innere eines Codeblocks - alles gegen einen echten Parser gehalten.
Markdown trägt Bedeutung in seiner Zeichensetzung
Markdown sieht aus wie Klartext mit Verzierung, weshalb es kostenlos wirkt, die Verzierung zu entfernen. Ist es nicht. Drei seiner Konstrukte tragen Information, die sonst nirgends im Dokument steht. Ein Link enthält zwei Dinge, den Text und das Ziel, von denen nur eines sichtbar ist; lösch die Syntax, und das Ziel geht mit. Eine verschachtelte Liste enthält eine Beziehung - dieser Kanal gehört zu jener Region -, vollständig in der Einrückung kodiert. Eine Tabelle enthält ein Gitter, und ein Gitter sind zwei Dimensionen, geschrieben in die eine Dimension des Textes.
Nimm einen kurzen Bericht: eine Überschrift zweiter Ebene, einen Satz mit einem Link und eine zweistufige Liste aus Regionen und ihren Kanälen. Lass einen naiven Entferner darüberlaufen - die übliche Musterliste für Überschriften, Hervorhebungen, Code-Abschnitte, Links und Aufzählungszeichen - und er kommt rund ein Drittel kürzer zurück, was nach guter Arbeit klingt, bis man ihn liest. Siehe die vollständige Aufschlüsselung für die Rohzahlen zeigt jetzt nirgendwohin. Laden: +4 %, Online: +11 % und Laden: unverändert stehen bündig neben Nordamerika und Europa, auf derselben Einrückung, sodass nichts mehr sagt, zu welcher Region welche Zahl gehört - und das Dokument enthält zwei verschiedene Laden-Zeilen, die einander nun widersprechen.
Markdown hat keine einzige Spezifikation
Die ursprüngliche Beschreibung von 2004 war ein Perl-Skript und eine Seite Prosa, keine Grammatik, und jede spätere Implementierung löste die Mehrdeutigkeiten anders auf. CommonMark gibt es, um das zu beheben: eine genaue Spezifikation mit einer Testsammlung. GitHub Flavored Markdown ist CommonMark plus vier Erweiterungen, und genau diese Erweiterungen sind die Konstrukte, die man für Bestandteile von Markdown hält. Schick dieselbe Eingabe durch einen Parser mit ein- und ausgeschalteten GFM-Erweiterungen, und der Unterschied ist sichtbar.
Eine Tabelle mit senkrechten Strichen wird unter GFM zu einer echten Tabelle und bleibt unter CommonMark ein Absatz mit wörtlichen Strichen. Zwei Tilden um ein Wort werden unter GFM zu einer Streichung und bleiben unter CommonMark zwei Tilden. Eine nackte https://-Adresse wird unter GFM zu einem Link und bleibt unter CommonMark Text. Und ein Listeneintrag, der mit einem eingeklammerten Leerzeichen oder x beginnt, wird unter GFM zu einem Kontrollkästchen und behält unter CommonMark seine wörtlichen Klammern. Jedes dieser Konstrukte erkennt dein Entferner entweder oder nicht - abhängig von einer Einstellung, die niemand aufgeschrieben hat.
Es gibt außerdem ein Konstrukt, das beide Spezifikationen teilen und das fast jeder Regex-Entferner vergisst: die Setext-Überschrift, eine Textzeile mit einer Reihe von Gleichheitszeichen oder Bindestrichen darunter. Sowohl CommonMark als auch GFM machen daraus eine Überschrift. Ein Entferner, dessen einzige Überschriftenregel führende Rauten erfasst, lässt die Reihe von Gleichheitszeichen als Satzzeichenzeile in der Ausgabe stehen.
Drei Dinge, die eine Regex falsch und ein Parser richtig macht
Zuerst der Unterstrich in einem Dateinamen. Lass einen naiven Entferner über Öffne bericht_final_v2.txt und dann archiv_2026_q1.csv laufen, und das Muster für Unterstrich-Hervorhebung frisst beide: berichtfinalv2.txt und archiv2026q1.csv. Ein CommonMark-Parser lässt den Satz genau so, wie er war, denn die Spezifikation sagt, dass ein Unterstrich im Wortinneren keine Hervorhebung öffnet oder schließt - diese Regel gibt es gerade, damit snake_case überlebt. Das Sternchen verhält sich hier anders als der Unterstrich, und schon das ist eine Regel, die eine Regex nicht ausdrücken kann.
Zweitens das Sternchen als Rechenzeichen. Die Fläche ist 2 * Breite * Höhe, also 2 * 3 * 4 = 24 kommt aus dem naiven Entferner als Die Fläche ist 2 Breite Höhe, also 2 3 4 = 24 heraus, jedes Sternchen verschwunden und ein doppeltes Leerzeichen an seiner Stelle. Der Parser rührt es nicht an, denn die Flankenregeln von CommonMark besagen, dass ein Begrenzer mit Leerraum auf beiden Seiten weder öffnen noch schließen kann. Die Regel ist genau, gut dokumentiert und etwa drei Sätze lang - und sie ist eine Regel über Kontext, den reguläre Ausdrücke bauartbedingt nicht sehen können.
Drittens der Referenzlink, dessen Ziel überhaupt nicht neben dem Text steht. Schreibe Siehe [den vollständigen Bericht][ber] für Details und setz [ber]: https://example.com/bericht-2026.pdf ans Ende des Dokuments - ein Parser fügt beides zu einem Link zusammen. Das Linkmuster des naiven Entferners erwartet eine Klammer, findet nichts und lässt sowohl die eckigen Klammern im Satz als auch die Definitionszeile am Fuß des Dokuments stehen; die Ausgabe ist also an zwei Stellen zugleich schlechter als die Eingabe. Nichts davon lässt sich mit einem weiteren Muster beheben: Einen Referenzlink aufzulösen heißt, Zustand über das ganze Dokument zu halten - und genau das ist ein Parser.
Codeblöcke: der Inhalt muss unangetastet überleben
Ein Codeblock ist die einzige Stelle in einem Markdown-Dokument, an der Markdown-Syntax keine Markdown-Syntax ist. Sein ganzer Zweck ist es, Zeichen zu halten, die exakt wiedergegeben werden müssen, und diese Zeichen enthalten regelmäßig Sternchen, Unterstriche und Rauten. Gib einem naiven Entferner einen eingezäunten Python-Block mit def f(*args), einer mit einer Raute beginnenden Kommentarzeile und einem mit Unterstrichen geschriebenen Bezeichner: Er macht drei verschiedene Fehler. Er frisst mit seinem Inline-Code-Muster einen der drei Zaun-Rückstriche, er entfernt die Unterstriche aus dem Bezeichner, und er lässt den Zaunrest in der Ausgabe stehen. Ein Parser markiert den ganzen Block als Code und schaut gar nicht hinein.
Der eingerückte Codeblock ist dieselbe Falle ohne sichtbaren Zaun. Vier Leerzeichen am Zeilenanfang erzeugen sowohl in CommonMark als auch in GFM einen Codeblock; ein Entferner, der nur Rückstriche kennt, schreibt den Inhalt also munter um. Ein Bezeichner a_b_c kommt als abc heraus, und ein mit einer Raute beginnender Kommentar ist der Überschriftenregel ausgeliefert. Wenn du den Entferner selbst schreibst: Erkenne zuerst die Codebereiche und maskiere sie, wende dann alle übrigen Regeln auf den Rest an und setz die maskierten Bereiche danach wortwörtlich wieder ein. Das ist ein Durchgang mehr, und er beseitigt eine ganze Fehlerklasse.
Was behalten, was verwerfen
Die brauchbare Regel lautet nicht „entferne die Syntax“, sondern „entferne die Syntax, die nur Formatierung trug, und schreibe die um, die Information trug“. Verwirf Überschriften-Rauten und Setext-Unterstreichungen, Hervorhebungszeichen, Codezäune, Zitatpfeile und waagerechte Linien: Keines davon sagt etwas, was die Wörter nicht sagen. Schreibe den Rest um. Ein Link wird zu seinem Text, gefolgt von seinem Ziel in Klammern. Ein Listenzeichen wird zu einem Aufzählungspunkt, und die Einrückung bleibt, denn dort wohnt die Hierarchie. Eine Tabelle wird zu einer Zeile je Reihe mit sichtbarem Trennzeichen zwischen den Zellen, und die Ausrichtungszeile verschwindet. Ein Bild wird zu seinem Alternativtext, dem einzigen Teil davon, der je aus Wörtern bestand.
Dasselbe Dokument, so behandelt, behält alles, was der naive Durchgang verloren hat. Die Überschrift ist weiterhin eine Zeile aus Wörtern, der Satz trägt sein Ziel weiterhin in Klammern, und die zweistufige Liste hat weiterhin zwei Stufen, sodass die vier Zahlen weiterhin zu den zwei Regionen gehören. Es ist länger als die naive Ausgabe, und genau diese Mehrlänge ist die Information, die die naive Ausgabe gelöscht hat.
Eine Abkürzung ist bekannt zu machen, samt der zugehörigen Warnung. Steht ohnehin ein echter Markdown-Parser bereit, ist der kürzeste korrekte Weg zum Klartext, das Markdown nach HTML zu rendern und dann den Text aus dem HTML zu ziehen, denn der Parser hat Referenzlinks, Codeblöcke und die Flankenregeln bereits für dich aufgelöst. Die Warnung: Die zweite Hälfte dieses Wegs ist ein eigenes Problem - HTML zu entfernen hat eine eigene Schrittreihenfolge, behandelt im Begleitartikel dieser Reihe, und es mit einer zweiten Regex zu tun führt genau die Fehlerklasse wieder ein, der du eben entkommen bist.
| Konstrukt | Ausgabe des Regex-Entferners | Was ein Parser tut | Behalten oder verwerfen |
|---|---|---|---|
| Inline-Link [Text](URL) | Text bleibt, Ziel gelöscht | Text und Ziel beide verfügbar | Beides behalten: Text, dann die URL in Klammern |
| Unterstriche in einem Dateinamen: bericht_final_v2.txt | berichtfinalv2.txt | Unverändert: Unterstriche im Wortinneren sind keine Hervorhebung | Behalten |
| Sternchen als Malzeichen: 2 * 3 * 4 | 2 3 4 | Unverändert: ein Begrenzer mit Leerzeichen auf beiden Seiten öffnet nichts | Behalten |
| Eingezäunter Codeblock | Frisst ein Zaun-Rückstrich und verändert den Code darin | Inhalt wortwörtlich erhalten | Zaun verwerfen, jedes Zeichen darin behalten |
| Referenzlink [Text][Ref] | Klammern überleben, und die Definitionszeile ebenfalls | Ziel wird aus der andernorts stehenden Definition aufgelöst | Text und Ziel behalten, die Definitionszeile verwerfen |
| Tabelle mit senkrechten Strichen | Eine Reihe von Wörtern, die Bindestrichzeile überlebt als Text | Zeilen und Zellen, und nur unter GFM - CommonMark kennt keine Tabellen | Zellen mit einem Trennzeichen behalten, die Ausrichtungszeile verwerfen |
Häufige Fragen
- Wohin verschwindet die Link-URL beim Entfernen von Markdown?
- In den meisten Entfernern ins Nichts. Das übliche Muster ersetzt das ganze Konstrukt [Text](URL) durch den erfassten Text: Siehe die [vollständige Aufschlüsselung](https://example.com/q3.pdf) wird zu Siehe die vollständige Aufschlüsselung - ein Satz, der ein Ziel verspricht, das er nicht mehr hat. Ist der Klartext für einen Menschen, behalte das Ziel in Klammern hinter dem Text; speist er einen Suchindex, behalte den Text und leg die URL in einem eigenen Feld ab. Ihn stillschweigend zu löschen ist die einzige Option ohne Anwendungsfall.
- Warum hat das Entfernen von Markdown meine Dateinamen verstümmelt?
- Weil der Entferner die Unterstriche für Hervorhebung hielt. Ein Muster aus einem Unterstrich, einer genügsamen Erfassung und einem weiteren Unterstrich trifft die Mitte von bericht_final_v2.txt und löscht beide Unterstriche, was berichtfinalv2.txt ergibt. CommonMark tut das bewusst nicht: Unterstriche im Wortinneren öffnen und schließen nie eine Hervorhebung - genau diese Regel hält snake_case-Bezeichner und Dateinamen unversehrt. Ein Entferner, der das falsch macht, setzt nicht Markdown um, sondern eine Vermutung über Markdown.
- Ist Markdown-Entfernen dasselbe wie nach HTML wandeln und die Tags entfernen?
- Es ist ein guter Weg und kein identischer. Das Rendern nach HTML mit einem echten Parser löst Referenzlinks, Codeblöcke und die Hervorhebungsregeln korrekt auf, und das ist der größte Teil der Schwierigkeit. Der zweite Schritt wirft aber genau das weg, was du behalten wolltest, sofern du dich nicht darum kümmerst: das href eines Ankers, das alt eines Bildes, die Zellgrenzen einer Tabelle. Zieh diese Attribute bewusst heraus, bevor du den Textinhalt nimmst, und denk daran, dass das Entfernen von HTML ein eigenes Reihenfolgeproblem hat, das in dieser Reihe gesondert behandelt wird.
- Was geschieht mit einer Tabelle?
- Unter einem naiven Entferner wird sie zu einer Reihe von Wörtern: Die senkrechten Striche werden zu Leerzeichen, und die Ausrichtungszeile aus Bindestrichen überlebt als Satzzeichenzeile, sodass eine Leserin vier Zahlenspalten bekommt, ohne dass etwas sagt, welche welche ist. Unter einem Parser ist sie ein Gitter, das du neu darstellen kannst: eine Zeile je Reihe, Zellen durch ein sichtbares Trennzeichen verbunden, Ausrichtungszeile verworfen. Beachte, dass eine Tabelle im strengen Sinn gar kein Markdown ist: Sie ist eine GFM-Erweiterung, und unter reinem CommonMark sind diese Strichzeilen ein gewöhnlicher Absatz.
- Muss der Entferner die GFM-Erweiterungen kennen?
- Wenn deine Dokumente von einem Code-Hoster, einem Ticketsystem oder einem Chat-Werkzeug stammen: ja. Tabellen, Durchstreichung, Autolinks für nackte URLs und Aufgabenlisten sind GFM-Erweiterungen, und ein reiner CommonMark-Entferner lässt deren Syntax als wörtliche Zeichen in der Ausgabe stehen - zwei Tilden um ein Wort, Klammern um ein Leerzeichen, Reihen von Strichen. Der umgekehrte Fehler existiert ebenso: GFM-Regeln auf ein für strenges CommonMark geschriebenes Dokument anzuwenden macht aus einem Absatz voller Striche eine Tabelle, die sein Autor nie geschrieben hat. Wähle die Variante passend zur Quelle und schreibe es neben den Code.
- Sollen Codeblöcke behalten oder entfernt werden?
- Behalte ihren Inhalt und entferne nur den Zaun. Was nie geschehen darf, ist die mittlere Variante, bei der der Zaun verschwindet und danach die Regeln für Hervorhebung, Überschriften und Inline-Code über den Code darin laufen: Das erzeugt Text, der wie Code aussieht, aber nicht der geschriebene Code ist - schlimmer als beide Extreme. Speist dein Klartext eine Zusammenfassung oder einen Suchindex und fügt Code nur Rauschen hinzu, verwirf den Block ganz und lass eine Markierung an seiner Stelle. Das Innere eines Codeblocks zu verändern ist das Einzige, wofür es keine vertretbare Lesart gibt.
Artikel, die dich interessieren könnten
Alle Ratgeber →Ähnliche Tools
Quellen
- CommonMark — CommonMark Specification — emphasis and strong emphasis, code spans, fenced and indented code blocks, link reference definitions
- GitHub — GitHub Flavored Markdown Spec — tables, task list items, strikethrough and autolink extensions
- IETF — RFC 7763 and RFC 7764 — the text/markdown media type and known variants
- WHATWG — HTML Standard — parsing and the text content of elements
- MDN Web Docs — Node.textContent and the difference between text content and rendered text
Hast du einen Fehler in diesem Artikel entdeckt?