Un petit dilemne pour les expérimentés des regex !

WRInaute accro
bonjour,

J'ai un véritable dilemne !
Je vais essayer de poser le problème du mieux que possible (si j'oublie un élément, faites le moi savoir).

Donc voila je m'explique: je souhaite rechercher un élément interdit (balise bbcode) se trouvant entre deux autres balises bbcode.
Les exemples permettrons d'illustrer:

*cas valable:
[p]Super texte !![/p][hr/]

*cas non valable:
[p]Super texte !![hr/][/p]

Sachant que le [hr/] peut être positionné n'importe ou:
[p]Super [hr/]texte !![/p]

J'ai donc fais cela:
$text = preg_replace('`\[p\](.+)(\[hr\/\])(.+)\[\/p\]`Us', '[p]$1[HR/]$3[/p]', $text);
mais le problème qui se pose est le suivant:
si j'ai:
[p]Super texte !![/p]
[hr/]
[p]Super texte !![/p]

il va me le prendre en compte car il prend le premier [p] et le dernier [/p].
De plus j'aimerais pouvoir lui dire soit [hr/] soit par exemple [br/]. Je n'ai pas réussi à intégrer le "OU".

Voila ! en espérant pouvoir trouver de l'aide.
Merci.
 
WRInaute impliqué
L'approche par expressions régulières n'est pas évidente dans la conception d'un "langage".

Deux approches plus évidentes sont l'automate à état et le lexer. Je crois qu'il y a des classes disponibles sur PEAR pour ces deux tâches.
 
WRInaute accro
thierry8 a dit:
*cas valable:
[p]Super texte !![/p][hr/]

*cas non valable:
[p]Super texte !![hr/][/p]

Sachant que le [hr/] peut être positionné n'importe ou:
[p]Super [hr/]texte !![/p]

J'ai donc fais cela:
$text = preg_replace('`\[p\](.+)(\[hr\/\])(.+)\[\/p\]`Us', '[p]$1[HR/]$3[/p]', $text);
mais le problème qui se pose est le suivant:
si j'ai:
[p]Super texte !![/p]
[hr/]
[p]Super texte !![/p]

il va me le prendre en compte car il prend le premier [p] et le dernier [/p].
De plus j'aimerais pouvoir lui dire soit [hr/] soit par exemple [br/]. Je n'ai pas réussi à intégrer le "OU".

Voila ! en espérant pouvoir trouver de l'aide.
Merci.

Bonjour

Donc le problème est:

"Sélectionner toute expression sur une ou plusieurs lignes, contenant l'expression [hr/] entre l'expression [p] et la plus proche expression[/p]

Ce qui signifie, sélectionner:

"\[p\]([^(\[(\/p)|(hr\/)\])]*(\[hr\/\]))+[.]*\[\/p\]"

Voilà, normalement cette expression régulière Posix, ne sélectionne que les cas où les expressions [p] et [/p] les plus proches l'unes de l'autre, sont séparées par une ou plusieurs expressions [hr/]. Malheureusement, il sélectionne aussi dans le cas où le texte autre que les tokens [hr/], [p] et [/p], est réduit à une chaîne vide.

L'expression: [^(\[(\/p)|(hr\/)\])] signifie: "Tout sauf le token [/p] ou le token [hr/] "

Peut-être la parenthèse englobante n'est-elle pas nécessaire...

Il est nécessaire que cette expression soit suivie par l'étoile *, car le token [hr/] peut être immédiatement après le premier token [p].

D'autre part il se peut que le token [hr/] existe en plusieurs exemplaires, ce qui complique effectivement le problème du remplacement. Je ne connais pas preg_replace().

Donc, plusieurs séquences

Celà dit, il est vrai que le rôle ultime d'un lexer, est d'interpréter des séquences d'exprsssions régukières, et qu'il est tout à fait possible de faire un lexer, et même un parser complet, en PHP...

Le tout est de cibler ce que tu veux sélectionner, et de ne pas te tromper, dans la logique de la sélection.

Bien à toi.

Amicalement.

Jean-François Ortolo
 
Discussions similaires
Haut