RegEx-Grundlagen für Apache-Regeln
Der Ausschnitt regulärer Ausdrücke, den RewriteRule und RedirectMatch tatsächlich brauchen: Anker, Zeichenklassen, Quantoren, Gruppen und die Unterschiede zwischen den beiden Direktiven.
Das Wichtigste
-
RewriteRulesieht den Pfad ohne führenden Schrägstrich,RedirectMatchmit. Derselbe Ausdruck greift deshalb nicht in beiden Direktiven. - Ohne
^und$ist ein Muster ein Teilstring-Treffer. Genau daran scheitern die meisten zu breiten Regeln. - Der Punkt steht für ein beliebiges Zeichen. Ein Dateiname wie
seite.htmgehört alsseite\\.htmgeschrieben. - Gruppen in Klammern landen als
$1,$2im Ziel. Aus einerRewriteCondholst du sie dagegen mit%1.
Für .htaccess-Regeln brauchst du keinen vollständigen Kurs in regulären Ausdrücken. Es reicht ein kleiner, klar umrissener Teil der Syntax, und der lässt sich in zwanzig Minuten lernen.
Anker: der wichtigste Teil
Ohne Anker ist ein Muster ein Teilstring-Treffer. Das ist die Ursache für praktisch jede Regel, die zu viel abfängt.
| Muster | trifft | trifft auch |
|---|---|---|
produkte | produkte/ | alte-produkte-liste/, x/produkte.htm |
^produkte | produkte/ | produkte-alt/ |
^produkte/ | produkte/schuhe/ | – |
^produkte/$ | nur produkte/ | – |
^ bindet an den Anfang, $ an das Ende. In einer RewriteRule ist der Anfang der Pfad ohne führenden Schrägstrich, weil Apache ihn vorher relativ zum Verzeichnis auflöst. In RedirectMatch ist er dagegen mit Schrägstrich. Dasselbe Muster verhält sich in beiden Direktiven also unterschiedlich:
RewriteRule ^produkte/(.*)$ /shop/$1 [R=301,L]
RedirectMatch 301 ^/produkte/(.*)$ /shop/$1
Zeichenklassen und Quantoren
| Zeichen | Bedeutung |
|---|---|
. | ein beliebiges Zeichen |
\d | eine Ziffer |
\w | Buchstabe, Ziffer oder Unterstrich |
[a-z0-9-] | genau eines dieser Zeichen |
[^/] | alles ausser einem Schrägstrich |
* | null oder mehr |
+ | eins oder mehr |
? | null oder eins |
{2,4} | zwei bis vier |
Der Punkt ist die häufigste Falle. In seite.htm steht er für ein beliebiges Zeichen, das Muster trifft also auch seiteXhtm. Richtig ist seite\.htm.
Praktisches Beispiel für eine Artikel-URL mit numerischer ID:
# archiv-artikel_97_greylisting.htm -> /artikel/greylisting/
RewriteRule ^archiv-artikel_(\d+)_([a-z0-9_]+)\.htm$ /artikel/$2/ [R=301,L]
(\d+) fängt die ID, ([a-z0-9_]+) den sprechenden Teil. Beides steht anschliessend als $1 und $2 zur Verfügung.
Gruppen: $1 aus der Regel, %1 aus der Bedingung
Klammern erzeugen eine Gruppe. Woher du sie später holst, hängt davon ab, wo sie stand:
# Gruppe aus der RewriteCond -> %1
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L,NE]
# Gruppe aus der RewriteRule -> $1
RewriteRule ^blog/(.*)$ /artikel/$1 [R=301,L]
Diese Verwechslung erzeugt keine Fehlermeldung, sondern eine leere Ersetzung. Das Ergebnis ist eine Weiterleitung auf https:///pfad oder ein 500er, je nach Konstellation.
Wenn du eine Gruppe nur zum Zusammenfassen brauchst und nicht referenzieren willst, spart (?:...) den Zähler:
RewriteCond %{HTTP_HOST} ^(?:www\.)?alte-domain\.de$ [NC]
Alternativen und optionale Teile
Der senkrechte Strich trennt Alternativen, das Fragezeichen macht den vorangehenden Teil optional:
# fängt .htm und .html
RewriteRule ^doku_(htaccess|regex|modauth)\.html?$ /apache/htaccess/ [R=301,L]
html? heisst: htm, gefolgt von einem optionalen l. Die Alternativen in der ersten Gruppe sind bewusst aufgezählt statt mit .* erschlagen – so kann die Regel nichts abfangen, was du nicht kennst.
Greedy oder nicht
.* ist gierig und nimmt so viel wie möglich. Bei verschachtelten Pfaden führt das zu falschen Treffern:
# nimmt bei /a/b/c/ alles bis zum letzten Schrägstrich
RewriteRule ^(.*)/(.*)$ ...
# nimmt bei /a/b/c/ nur bis zum ersten
RewriteRule ^([^/]+)/(.*)$ ...
[^/]+ ist in Pfadregeln fast immer die bessere Wahl als .*, weil es an Verzeichnisgrenzen stoppt.
Testen, bevor es live geht
Reguläre Ausdrücke lassen sich ohne Apache prüfen. Für einen schnellen Gegentest reicht grep mit erweiterten Ausdrücken:
# trifft das Muster die erwarteten Alt-URLs - und nur die?
grep -E '^archiv-artikel_[0-9]+_[a-z0-9_]+\.htm$' alt-urls.txt
Nimm dafür die echte Alt-URL-Liste aus Logfile oder Backlink-Export. Ein Muster, das gegen fünf ausgedachte Beispiele funktioniert, sagt wenig über 3.000 gewachsene URLs.
Häufige Fragen
Warum greift meine Regel auf mehr URLs als gedacht?
Vermutlich fehlen die Anker. Ohne ^ am Anfang und $ am Ende sucht Apache das Muster irgendwo im Pfad. Die Regel ^produkte matcht damit auch /alte-produkte-liste/.
Was ist der Unterschied zwischen $1 und %1?
Mit dem Dollarzeichen greifst du auf Gruppen aus dem Muster der RewriteRule zu, mit dem Prozentzeichen auf Gruppen aus der zuletzt ausgewerteten RewriteCond. Wer die beiden verwechselt, bekommt ein leeres Ergebnis statt einer Fehlermeldung.
Muss ich Sonderzeichen im Muster maskieren?
Punkt, Fragezeichen, Plus, Sternchen, Klammern und der senkrechte Strich haben in regulären Ausdrücken eine Bedeutung. Sollen sie wörtlich gelten, gehört ein Backslash davor. Der Schrägstrich braucht in Apache keine Maskierung.
Ist die Auswertung von Gross- und Kleinschreibung abhängig?
Ja, standardmässig unterscheidet Apache. Mit dem Flag [NC] wird die Regel unempfindlich. Bei Host-Prüfungen ist [NC] fast immer richtig, bei Pfaden solltest du bewusst entscheiden.
Weiterlesen
- 301-Weiterleitungen richtig schreiben
Redirect, RedirectMatch und RewriteRule im Vergleich, Endlosschleifen vermeiden, Query-Strings erhalten, Domainwechsel sauber abbilden.
- .htaccess: Der vollständige Praxisleitfaden
Aufbau, Reihenfolge der Direktiven, Rewrite-Engine, Fehlerseiten, Zugriffsschutz und Caching - mit den Fallen, die erst live auffallen.
- Verzeichnisschutz mit mod_auth einrichten
Basic Auth per .htpasswd, Ausnahmen für einzelne Dateien, IP-Freigaben und warum Basic Auth ohne HTTPS wertlos ist.
- Apache-Grundkonfiguration verstehen
VirtualHost, Module, MPM-Auswahl und Logformate: die Stellschrauben außerhalb der .htaccess.