$text = preg_replace('#(\r\n){2,}#', "\r\n", $text);
Beim ersten Argument ist es egal, ob du es in " oder ' setzt. Bei " erkennt PHP das \r\n und ersetzt es durch die Zeilenumbruchszeichen, bei ' wird \r\n durchgereicht und die RegExp-Machine interpretiert sie als Zeilenumbruchszeichen.
Und zur Erklärung des Ausdrucks
sind die begrenzer, der eigentliche Ausdruck steht dazwischen.
(\r\n) ist ein Untermuster das gefunden wird, {} ist ein Quantifikator - wie auch + oder *.
{2} ist z.B. "vorhergehendes 2x", {2,6} wäre "mindestens 2x, maximal 6x", {2,} entspricht "mindestens 2x, maximal egal"
Die Quantifikatoren + und * entsprechen übrigens {1,} bzw. {0,}.