PHP-Code:
$out = preg_replace('/(.)(\\1{1,2})\\1*/sS', '$1$2', $in);
Zerlegen wir das Ganze mal:
. passt auf jedes beliebige Zeichen (wenn ganz am Ende /s steht).
(.) Wie der Punkt. Weil er aber in runden Klammern steht, wird das das gefundene Muster zwischengespeichert und durchnummeriert. Sowas nennt man "subpattern". Weil es sich um das erste runde Klammernpaar handelt, bekommt dieses Subpattern die Nummer 1.
\\1 findet exakt das gleiche, wie das
erste Subpattern. Das nennt man "back reference".
\\1{1,2} findet das gleiche, wie das erste Subpattern, und zwar mehrere Male. Hier mindestens 1 Mal und höchstens 2 Mal.
(\\1{1,2}) Merkt sich diesen Kram für später als Subpattern Nummer 2.
\\1* findet das gleiche, wie das erste Subpattern, und zwar mehrere Male. Der Stern steht hier für null mal bis beliebig oft.
Beim Ersetzen geben wir die Nummer der "gemerkten" Subpattern an:
$1 ist das, was mit (.) gefunden wurde.
$2 ist das, was mit (\\1{1,2}) gefunden wurde.
Das Geheimnis sind die Zahlen in den geschweiften Klammern.
Die erste gibt eine Minimalzahl an und die zweite die Maximalzahl.
Willst du jetzt 5 Zeichen stehen lassen, schreibst du:
PHP-Code:
$out = preg_replace('/(.)(\\1{1,4})\\1*/sS', '$1$2', $in);
Das findet und behält mindestens 1 + 1 == 2 Zeichen und maximal 1 + 4 == 5 Zeichen. Alle weiteren Zeichen werden entfernt.
Ich hoffe, das war jetzt nicht noch verwirrender als nur der reguläre Ausdruck alleine ...
Alternativ könntest du auch eine Funktion schreiben, die die maximale Zahl zu erhaltender gleicher Zeichen entgegennimmt und dann den regulären Ausdruck zusammenbaut:
PHP-Code:
function many_to_few(
$in /// STR string to filter
$max /// INT(3...) maximale Anzahl
) {
if (!is_num($max) || $max < 3) {
return FALSE;
}
return preg_replace('/(.)(\\1{1,' . $max - 1 . '})\\1*/sS', '$1$2', $in);
}