preg_replace

tomyv

Grünschnabel
Hallo,
ich setze beim Ausführen der Suchfunktion den Suchbegriff im gesamten HTML-Sourcecode in <mark>-Tags. Das mache ich mittels preg_replace mit folgendem command:
PHP:
$return = preg_replace("/($keyword)/i", "<mark>$0</mark>", $text);
Im vorliegenden Beispiel ist der Suchbegriff zB 'Jakarta' und der Begriff wurde nun auch innerhalb des <a>-Tags zwischen die <mark>-Tags gesetzt (rot), was unterbunden gehört.

Kann mir jemand sagen, wie ich Command erweitern muss, damit innerhalb der <a>-Tags keine <mark>-Tags gesetzt werden?
Besten Dank im voraus, Thomas
...
<p style='font-weight:bold; font-size: 14px; '>Padang - <mark>Jakarta</mark> Post 2: An der südwestlichen Küste Sumatras</p>
...
<a href='Padang-RI-<mark>Jakarta</mark>-2023-01-02.337.0.html'>Das-ist-der-Link</a>
...
 
Lösung
Allgemein und bei Regex lerne ich immer gern dazu. Die automatischen Erklärungen bei dem Regex-Tester sind jedoch beinahe so kryptisch wie die Regex selber. Bist Du vielleicht so freundlich, das ein wenig zu erklären.
Code:
(?:<[^>]*(*SKIP)|)(Jakarta)
  1. Annahme wie bei dir. überall innerhalb <..> soll nichts geändert werden, denn dort sind nur Attribute zu den Tags
  2. Positive Suchraster sind einfacher als Negative. In dem Fall: <[^>]*. < gefolgt von allem möglichen ausser >.
  3. (*SKIP) Ist mir auch neu und die Infos auf deutsch sind spärlich. Geht auch nur in wenigen Sprachen. Für PHP geht es.
    Ich glaube in etwa: wenn alles bis hierhin stimmt, dann skippe den kompletten Fund und suche erst nach dem kompletten...
Wenn ich das richtig überblicke, muss der Suchbegriff zwischen einer schließenden und einer öffnenden spitzen Klammer stehen. Dies funktioniert bei mir:
Code:
    $keyword = 'Jakarta';
    $str = "<a href='Padang-RI-Jakarta-2023-01-02.337.0.html'>Padang - Jakarta</a>
        <p style='font-weight:bold; font-size: 14px; '>Padang - Jakarta Post 2: An der südwestlichen Küste Sumatras</p>";
    $strMarked = preg_replace("/(>[^>]*)($keyword)([^<]*<)/i", "$1<mark>$2</mark>$3", $str);
    var_dump($strMarked);
 
Wenn ich das richtig überblicke, muss der Suchbegriff zwischen einer schließenden und einer öffnenden spitzen Klammer stehen. Dies funktioniert bei mir:
Code:
    $keyword = 'Jakarta';
    $str = "<a href='Padang-RI-Jakarta-2023-01-02.337.0.html'>Padang - Jakarta</a>
        <p style='font-weight:bold; font-size: 14px; '>Padang - Jakarta Post 2: An der südwestlichen Küste Sumatras</p>";
    $strMarked = preg_replace("/(>[^>]*)($keyword)([^<]*<)/i", "$1<mark>$2</mark>$3", $str);
    var_dump($strMarked);
Danke für deine Antwort - funktioniert leider nicht, im Lijnk befinden sich noch immer die <mark>-tags
1681827735527.png
 
Hm, mit meinem Testcode hatte es funktioniert, Ausgabe:
<a href='Padang-RI-Jakarta-2023-01-02.337.0.html'>Padang - <mark>Jakarta</mark></a>
<p style='font-weight:bold; font-size: 14px; '>Padang - <mark>Jakarta</mark> Post 2: An der südwestlichen Küste Sumatras</p>
Im href-Attribut ist nichts markiert.
Poste doch mal den vollständigen String, mit dem Du getestet hast.
 
Allgemein und bei Regex lerne ich immer gern dazu. Die automatischen Erklärungen bei dem Regex-Tester sind jedoch beinahe so kryptisch wie die Regex selber. Bist Du vielleicht so freundlich, das ein wenig zu erklären.
 
Allgemein und bei Regex lerne ich immer gern dazu. Die automatischen Erklärungen bei dem Regex-Tester sind jedoch beinahe so kryptisch wie die Regex selber. Bist Du vielleicht so freundlich, das ein wenig zu erklären.
Code:
(?:<[^>]*(*SKIP)|)(Jakarta)
  1. Annahme wie bei dir. überall innerhalb <..> soll nichts geändert werden, denn dort sind nur Attribute zu den Tags
  2. Positive Suchraster sind einfacher als Negative. In dem Fall: <[^>]*. < gefolgt von allem möglichen ausser >.
  3. (*SKIP) Ist mir auch neu und die Infos auf deutsch sind spärlich. Geht auch nur in wenigen Sprachen. Für PHP geht es.
    Ich glaube in etwa: wenn alles bis hierhin stimmt, dann skippe den kompletten Fund und suche erst nach dem kompletten Fund weiter. Also skippe <...Jakarta
  4. Der SKIP in ein "oder" (?:..|) gepackt, damit Jakarta ohne offenen Tag findet. Man kann den ODER auch so schreiben, damit klar wird was gemeint ist. (?:<[^>]*Jakarta(*SKIP)|(Jakarta)).
Nachtrag: Ich habe Das Pattern zu meinem ersten Posting noch angepasst. aus [^<>] habe ich [^>] gemacht, da innerhalb eines Tagsbefehls kein weiterer geöffnet werden kann und somit der < überflüssig ist. regex101: build, test, and debug regex
 
Lösung
Vielen lieben Dank, das hilft mir weiter. Mit SKIP etwas Neues gelernt und mit dem ?: muss ich mich auch noch vertraut machen.
 
Code:
(?:<[^>]*(*SKIP)|)(Jakarta)
  1. Annahme wie bei dir. überall innerhalb <..> soll nichts geändert werden, denn dort sind nur Attribute zu den Tags
  2. Positive Suchraster sind einfacher als Negative. In dem Fall: <[^>]*. < gefolgt von allem möglichen ausser >.
  3. (*SKIP) Ist mir auch neu und die Infos auf deutsch sind spärlich. Geht auch nur in wenigen Sprachen. Für PHP geht es.
    Ich glaube in etwa: wenn alles bis hierhin stimmt, dann skippe den kompletten Fund und suche erst nach dem kompletten Fund weiter. Also skippe <...Jakarta
  4. Der SKIP in ein "oder" (?:..|) gepackt, damit Jakarta ohne offenen Tag findet. Man kann den ODER auch so schreiben, damit klar wird was gemeint ist. (?:<[^>]*Jakarta(*SKIP)|(Jakarta)).
Nachtrag: Ich habe Das Pattern zu meinem ersten Posting noch angepasst. aus [^<>] habe ich [^>] gemacht, da innerhalb eines Tagsbefehls kein weiterer geöffnet werden kann und somit der < überflüssig ist. regex101: build, test, and debug regex
Vielen Dank! (y) Funktioniert genauso, wie ich es brauche - obwohl ich zugeben muss, dass ich es noch nicht ganz nachvollziehen kann ...
 

Neue Beiträge

Zurück