1

I have a problem with anchor in regex:

https://regex101.com/r/URG3eA/1/

All is working as excepted except for one case ! I don't want to selected the word "monnaie" if it is between anchor tag. (<a>). If the anchor tag is just after the word, that is working, the word is not selected but I don't succeed to do the same for the case where the anchor tag is just before the word.

For example, I don't want to select the word "monnaie" in that case :

<a class="esk-seo-plu-link" href="https://abc.quaidesbalises.com/tags/-de-paris">MONNAIE DE PARIS</a>

Ori Marko
  • 56,308
  • 23
  • 131
  • 233
  • 1
    You could skip it, https://regex101.com/r/URG3eA/2/. – chris85 Sep 19 '17 at 14:50
  • Fortunately in Pessac, people produces more interesting things than currency. – Casimir et Hippolyte Sep 19 '17 at 14:59
  • 1
    What about `(?!.*?)(\bmonnaie\b)(?!.*?<\/a>)`: https://regex101.com/r/URG3eA/3 – ctwheels Sep 19 '17 at 15:04
  • @ctwheels: no this doesn't prove anything see: https://regex101.com/r/kEueH9/1 . You obtain the good result only because the s modifier is missing. – Casimir et Hippolyte Sep 19 '17 at 18:38
  • @CasimiretHippolyte you are completely correct. My solution only works due to newline characters. – ctwheels Sep 19 '17 at 19:05
  • Thanks a lot @ctwheels ! That's exactly what I need ! – Maxime Deuton Sep 20 '17 at 21:32
  • You should be cautious with the regex I wrote above. It only works for the case you've given but will not work without newline characters separating sections with and without anchors. Be wary when using my regex. See @CasimiretHippolyte's response to my regex for more information. – ctwheels Sep 20 '17 at 21:35
  • @ctwheels What about cases like dev.fr/tags/monnaie or dev.fr/tags/monnaie-some-words where "monnaie" is selected ? When I put \- or \/ in the negative lookahead, that doesn't work. – Maxime Deuton Sep 22 '17 at 10:17
  • @FrançoisDusautoir those are special cases not originally described. My regex uses `\b` which specifies any non-word character (`/` and `-` are non word characters). You can change it to a set inside a negative look ahead instead like `(?![^\/-])` which specifies not slash `/` or dash `-` – ctwheels Sep 22 '17 at 11:45

1 Answers1

0

I would recommend the stability/reliability of using DOMDocument & XPath, then use regex on text nodes that do not occur inside of <a> tags.

Using case-insensitive and multibyte pattern modifiers seems like an appropriate inclusion.

Code: (Demo)

$text = <<<TEXT
<div>
L’usine de Pessac, en Gironde, produit chaque jour environ 5 millions de pièces de monnaie. Leur fabrication repose sur des processus industriels extrêmement exigeants et de nombreuses manipulations. Des contrôles qualité sont effectuées à toutes les étapes. Celles-ci nécessitent des savoir-faire parfois multi-séculaires, mais aussi des techniques de pointe.

La gravure intervient ensuite pour concevoir et réaliser coins et poinçons. Ces matrices de frappe sont des blocs d’acier qui fonctionnent par paire, de manière à graver simultanément l’avers et le revers d’une monnaie. Ainsi, les effigies, inscriptions et éléments décoratifs d'une monnaie sont gravés en creux et à l’envers sur le coin, en relief et à l’endroit sur le poinçon.

<a href="">monnaie</a> est plus encore!

Les pièces fabriquées à Pessac sont mono-colores ou bi-colores : par un procédé breveté, la <a class="esk-seo-plu-link" href="https://abc.quaidesbalises.com/tags/monnaie-de-paris">Monnaie de Paris</a> peut assembler une couronne et un coeur au moment même de la frappe de la pièce. A noter que certaines monnaies de collection bénéficient d’une finition spéciale appelée « brillant universel ». Frappées avec un outillage neuf, ces pièces ont un aspect brillant et sont dépourvues de traces de dégradation, puisqu'elle n'ont jamais circulé.

MONNAIE DE PARIS: <a class="esk-seo-plu-link" href="https://abc.quaidesbalises.com/tags/-de-paris">MONNAIE DE PARIS</a> : c'est top
</div>
TEXT;

$pattern = '/\b' . preg_quote('monnaie', '/') . '\b/iu';

$dom = new DOMDocument; 
$dom->loadHTML($text, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);
foreach ($xpath->query("//*[not(ancestor-or-self::a)]/text()") as $node) {
    $node->nodeValue = preg_replace($pattern, "**$0**", $node->nodeValue);
}
echo utf8_decode($dom->saveHTML($dom->documentElement));

Output:

<div>
L’usine de Pessac, en Gironde, produit chaque jour environ 5 millions de pièces de **monnaie**. Leur fabrication repose sur des processus industriels extrêmement exigeants et de nombreuses manipulations. Des contrôles qualité sont effectuées à toutes les étapes. Celles-ci nécessitent des savoir-faire parfois multi-séculaires, mais aussi des techniques de pointe.

La gravure intervient ensuite pour concevoir et réaliser coins et poinçons. Ces matrices de frappe sont des blocs d’acier qui fonctionnent par paire, de manière à graver simultanément l’avers et le revers d’une **monnaie**. Ainsi, les effigies, inscriptions et éléments décoratifs d'une **monnaie** sont gravés en creux et à l’envers sur le coin, en relief et à l’endroit sur le poinçon.

<a href="">monnaie</a> est plus encore!

Les pièces fabriquées à Pessac sont mono-colores ou bi-colores : par un procédé breveté, la <a class="esk-seo-plu-link" href="https://abc.quaidesbalises.com/tags/monnaie-de-paris">Monnaie de Paris</a> peut assembler une couronne et un coeur au moment même de la frappe de la pièce. A noter que certaines monnaies de collection bénéficient d’une finition spéciale appelée « brillant universel ». Frappées avec un outillage neuf, ces pièces ont un aspect brillant et sont dépourvues de traces de dégradation, puisqu'elle n'ont jamais circulé.

**MONNAIE** DE PARIS: <a class="esk-seo-plu-link" href="https://abc.quaidesbalises.com/tags/-de-paris">MONNAIE DE PARIS</a> : c'est top
</div>

Note, I am using the advice from this answer to prevent the encoding of multibyte characters. This may or may not be necessary depending on what is happening in your application.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136