• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Ersetztes durch preg_replace nochmal ersetzen

Status
Für weitere Antworten geschlossen.

Durek

Neues Mitglied
Hallo,
ich habe eine Funktion für BB-Codes geschrieben, die auch super lief... Nur wenn ein Zitat in einem Zitat war wurde das nicht übernommen...
Deswegen habe ich eine Schleife gemacht, damit die Funktion 30x aufgerufen wird. Dies ist allerdings keine Alternative, da es sein kann, dass ein Zitat mehr als 30x dort drin oder gar nciht erst drin ist. Dies hier sehe ich als sehr unsauber an:
PHP:
<?php
function bbcode($message) {
$i = 1;
while ($i <= 30) {
$message = preg_replace('!\[QUOTE=(.*)\](.*)\[/QUOTE\]!isU', '<div class="quote"><b>Zitat von $1</b><br><i>$2</i></div>', $message);
$i++;
}
return $message;
}
?>
Bspw:
bla schrieb:

Ich hoffe ihr könnt mir helfen.
 
Zuletzt bearbeitet:
Werbung:
Du kannst doch direkt danach nochmal $message mit nem preg_replace() verändern.

Bsp:

PHP:
$zahl = 1;
$zahl++;
$zahl += 70

Erst wird die Variable auf 1 gesetzt, danach um eins erhöht und danach wird die 70 dazu addiert. Genauso kannst du es bei dir auch machen.


Hab aber eher nen Tipp für dich, dass du eben immer nur den Text des Vorgängers quoten lässt. Sodass gar nicht erst mehrere Quotes in einer entstehen, was unter anderem auch blöd aussieht :x
 
Hallo,

das geht mit conditional und recursive subpatterns.

PHP:
(?(condition)yes-pattern|no-pattern)
Für condition trägst du den regexp Code für den Anfang von quote ein und bei yes-pattern (?R) für den rekursiven Aufruf.

Das |no-pattern kannste unter umständen weglassen.


Oder alternativ zählste ob, genügend schließende zu den öffnenden vorhanden sind und wenn ja behandelst sie getrennt. Also erst alle [ quote=...] ersetzen und dann alle [/quote]


N43

P.S.: Die Variante mit dem rekursiven Aufruf ist eigentlich kein regulärer Ausdruck mehr, sondern bereits ein Keller-Automat.
 
Werbung:
Sn0opy -> das war allerdings nicht meine Frage^^
N43 -> Sorry, verstehe ich nicht ganz... auch googlen half mir nicht.


Danke euch beiden trotzdem und danke schonmal an möglicherweise noch kommende Lösungen^^
 
Sn0opy -> das war allerdings nicht meine Frage^^

Ich möchte dir nun nicht zu nahe treten, aber dann ist deni Topic ziemlich beschissen gewählt. Ein Topic sollte immer so gestellt sein, dass man sofort erkennen kann, worum es geht. Ich habe meine Antworte nun nach deinem Topic geschrieben.
 
Nein, es ging um eine andere Lösung und nicht das erneute Ersetzen, wie es bereits in meinem Beispiel vertreten wird. Von meiner Sicht ist das verständlich genug.
 
Werbung:
N43 -> Sorry, verstehe ich nicht ganz... auch googlen half mir nicht.
Ich hab's gestern nochmal probiert und selber nicht mehr ganz hinbekommen.

Ich würde einfach meine zweite Variante nehmen. Also
PHP:
$message = preg_replace('!\[quote=(.*)\]!isU', '<div class="quote"><b>Zitat von $1</b><br><i>', $message);
$message = str_replace ('[/quote]', '</i></div>', $message);

Musst dann nur aufpassen, dass nicht zu viele Quotes geöffnet oder geschlossen werden, sonst zerfetzt es dir ja das Design.


N43
 
du könntest die funktion preg_replace aufrufen und dann mit dem 5ten parameter die anzahl der ersetzten starttags ersetzen... danach diese als limit also als 4ten parameter für das ersetzen der close tags verwenden...

und fertisch :p
 
Ich hab's gestern nochmal probiert und selber nicht mehr ganz hinbekommen.

Ich würde einfach meine zweite Variante nehmen. Also
PHP:
$message = preg_replace('!\', '</i></div>', $message);

Musst dann nur aufpassen, dass nicht zu viele Quotes geöffnet oder geschlossen werden, sonst zerfetzt es dir ja das Design.


N43

Daran habe ich schon gedacht nur leider besteht dann das Problem, dass manche Spaßvögel im Forum dann in den HTML-Code "eingreifen" können und möglicherweise das Design abändern können. Naja ok... wenn es da vorerst keine Lösung gibt, dann liegt es wohl in der Aufgabe der Moderatoren soetwas zu löschen.

Also , dass man jetzt ohne einen Endtag HTML "einsetzen" kann. Vielleicht einfach mal das Thema offen lassen und schaun' was passiert^^


Aber danke trotzdem.
 
Werbung:
1. Durek du hast aaaarge probleme.
2. Ich habe Die lösung glaube ich gepostet...
 
nimm einfach die Technik mit dem Kellerautomaten.

Hab mal versucht sowas in der art zu basteln:
PHP:
<?php
class Quotes {
  public function __construct($text) {
    $this->text = $text;
    $this->keller = array("#");
  }
  public function text() {
    $this->_kellerappend();
    $this->_kellerremove();
    if (array_pop($this->keller) == "#") {
      $this->_replace();
    }
    return $this->text;
  }
  protected function _kellerappend() {
    preg_match_all('/\[quote.*?\]/is',$this->text,$treffer);
    for ($i = 0; $i < count($treffer[0]); $i++) {
      $this->keller[] = "q";
    }
  }
  protected function _kellerremove() {
    preg_match_all('/\[\/quote\]/is',$this->text,$treffer);
    for ($i = 0; $i < count($treffer[0]); $i++) {
      array_pop($this->keller);
    }
  }
  protected function _replace() {
    $pattern = "/\[quote\]/is";
    $replace = "<div class=\"quote\">";
    $this->text = preg_replace($pattern,$replace,$this->text);

    $pattern = "/\[quote=(.*?)\]/is";
    $replace = "<div class=\"quote\"><span class=\"author\">$1</span>";
    $this->text = preg_replace($pattern,$replace,$this->text);

    $pattern = "/\[\/quote\]/is";
    $replace = "</div>";
    $this->text = preg_replace($pattern,$replace,$this->text);
  }
  public function __destruct() {
    unset($this->text);
    unset($this->keller);
  }
}
$qoutes = new Quotes("Test[quote=Frank]Test[/quote]");
print $qoutes->text();
?>
 
oder du machst es so

PHP:
<?php

function check_text($text)
{
    $text = strtolower($text);
    $a1 = substr_count($text, '[quote]');
    $a2 = substr_count($text, '[/quote]');
    if($a1 == $a2){ return true; }
    return false;
}

?>

also einfach checken ob jemand die falsche anzahl an quotes gesetzt hat und wenn ja dann verbietest du ihm einfach den text zu posten und sagst ihm das er ihn nochmal bearbeiten muss ^^
 
Werbung:
also einfach checken ob jemand die falsche anzahl an quotes gesetzt hat und wenn ja dann verbietest du ihm einfach den text zu posten und sagst ihm das er ihn nochmal bearbeiten muss ^^

Und wie kann ich Platzhalter setzen? also es soll ja
NAME schrieb:
sein und nicht einfach nur
?
Ansonsten gute Lösung.

PS: Frank... danke für deine Mühe aber ich glaube, dass es durch Slibbo's Lösung um einiges einfacher ist.
 
ist mir schon klar, aber sie funktioniert wenigstens.

substr_count mit platzhalter wäre mir neu, wenn dann überhaupt mit preg_match_all und dem &$matches attribut.
 
Ok, aufjedenfall danke.
Aber ich habe noch nie eine Klasse gebildet. Funktionen habe ich drauf aber Klassen müsste ich noch mehr lernen, bevor ich eine fertige übernehme.
 
Werbung:
eine Klasse ist grob gesprochen nur ein zusammenschluss mehrere Funktionen. Diese werden dann, weil sie in einer Klasse sind, Methoden genannt.

Der Vorteil an der Klasse ist, das ich Variablen innerhalb der verschiedenen Methoden nicht immer übergeben muss, sondern sie mit dem keyword this semi-global (also in der ganzen klasse) verfügbar sind.

Die Klasse die ich gepostet habe, kannst du im Grunde genommen auch in einfach Funktionen aufteilen. Sähe dann so aus:
PHP:
function qoutes($text) {
  $keller = array("#");
  kellerappend($keller,$text);
  kellerremove($keller,$text);
  if (array_pop($keller) == "#") {
    replace($text);
  }
  return $text;
}
function kellerappend(&$keller,$text) {
  preg_match_all('/\[quote.*?\]/is',$text,$treffer);
  for ($i = 0; $i < count($treffer[0]); $i++) {
      $keller[] = "q";
  }
} 
function kellerremove(&$keller,$text) {
  preg_match_all('/\[\/quote\]/is',$text,$treffer);
  for ($i = 0; $i < count($treffer[0]); $i++) {
    array_pop($keller);
  }
}
function replace(&$text) {
  $pattern = "/\[quote\]/is";
  $replace = "<div class=\"quote\">";
  $text = preg_replace($pattern,$replace,$text);

  $pattern = "/\[quote=(.*?)\]/is";
  $replace = "<div class=\"quote\"><span class=\"author\">$1</span>";
  $text = preg_replace($pattern,$replace,$text);

  $pattern = "/\[\/quote\]/is";
  $replace = "</div>";
  $text = preg_replace($pattern,$replace,$text);
}

echo quotes("bla[quote]blubb[/quote]");

Im Vergleich dazu, finde ich die Klasse halt irgendwie doch noch etwas einfacher. OOP ist generell schön xD
 
ok, dann werde ich dieses doch nochmal überdenken und möglicherweise deine Klasse oder alternativ auch die Funktionen nehmen. Ich schau mir das mal an^^
 
Abend,

abgesehen davon, dass die Funktionen keinen gültigen Keller simulieren (man darf in der Eingabe nicht hin und her springen) sind sie völlig überdimensioniert.

Ob gleich viele Treffer gefunden wurden kann man doch mit einem Schlag vergleichen. Einfach Slibbo's Variante leicht modifizieren.

PHP:
<?php

function check_text($text)
{
    $text = strtolower($text);
    preg_match_all('/\[quote.*?\]/is',$text,$treffer); 
    $quote_open = count($treffer[0]);
    $quote_close = substr_count($text, '[/quote]');
    
    return ($quote_open == $quote_close);
}

?>


Jetzt fehlt aber noch die Berücksichtigung der Reihenfolge. Denn so kann ja [/quote] ... [quote ] verwendet werden. An der Stelle versagt auch die Klasse, gerade weil in der Implementierung im Text hin und her gesprungen wird (bzw. an den Anfang zurück).


Ich hab nochmal mit dem rekursiven preg regexp rum gespielt. preg scheint da nur rekursiv zu matchen, aber nicht rekursiv zu ersetzen. Das musste man dann "von Hand" machen:
PHP:
<?php

	function replace_quotes ($text, $from = null) {
		if ($from !== null) {
			$text = substr (
						$text,
						strpos ($text, ']') + 1,
						-1 * strlen ('[/quote]'));
		}

		$text = preg_replace (
			'!\[quote=(.*?)\]((?>\[)(?R)|.)*\[/quote\]!ise',
			"replace_quotes('$0', '$1')",
			$text);

		if ($from !== null) {
			return '<quote=' . $from . '>' . $text . '</quote>';
		} else {
			return $text;
		}
	}

	$text = 'test [quote=foo]test1[quote=bar]test2[/quote]ddd[/quote] ggl';
	echo replace_quotes ($text) . "\n";

?>


Musst im return noch anpassen, das er richtig ersetzt.

edit: War noch ein kleiner Fehler im regexp.

N43
 
Zuletzt bearbeitet:
Werbung:
PHP:
        do {
            $message = preg_replace("#\[quote\](.*?)\[/quote\]#si",'<div class="quote"><b>Zitat von \\$1</b><br><i>\\$2</i></div>', $message);
        } while(preg_match("#\[quote\].*\[/quote\]#si",$message));
 
Status
Für weitere Antworten geschlossen.
Zurück
Oben