2017-08-15 3 views
2

Mon modèle actuel est le suivant:PHP Regex match soit sur ou un mot sans utiliser de crochets?

pattern=("/(.*)(\bIf you want\b)(.*)/iu"); 

Mais avec:

preg_replace($pattern, '$1*$2*$3', $result); 

Ainsi, les trois parties doivent être remplacés car ils sont le 1 $, 2 $ et 3 $, mais je veux permettre une plus grande flexibilité donc je peux détecter par exemple ces deux lignes:

If you want 
If I want 

donc je pourrais simplement faire ceci:

pattern=("/(.*)(\bIf (I|you) want\b)(.*)/iu"); 

mais cela crée un problème puisque j'ai besoin de remplacer $ 1, $ 2 et $ 3. Les motifs sont insérés dynamiquement et sont donc toutes différentes:

$pattern = "/(.*)(\b".$value."\b)(.*)/iu"; 

La valeur $ a parfois un modificateur comme dans l'exemple ci-dessus « si (vous | I) voulez », mais d'autres motifs peuvent être simplement « ce qui est arrivé à côté » sans modificateur. Donc, les crochets supplémentaires causent un problème, mais je ne peux pas trouver un autre moyen de le faire.

EDIT: Veuillez noter que le problème est ici avec le preg_replace $ 1, $ 2 et $ 3. Avec un modèle comme

"/(.*)(\bwhat happened next\b)(.*)/iu" 

cela va bien à travers, mais avec un support supplémentaire comme avec

"/(.*)(\bIf (I|you) want\b)(.*)/iu" 

il ne remplacera pas correctement avec le 1 $, 2 $ et 3 $ preg_replace.

Aussi je me rends compte qu'il peut être fait comme ça

If you want|If I want 

Mais ce ne est pas particulièrement éloquent!

+1

Voulez-vous dire que $ value' peut contenir un motif défini par l'utilisateur? Vous ne pouvez pas utiliser des groupes qui ne capturent pas - '" /(.*)(\bIf (?: Je | vous) veux \ b) (. *)/Iu "' –

+0

Vous ne savez pas exactement ce que vous voulez dire. Le problème vient dans le preg_replace où il remplace les trois requêtes entre crochets avec $ 1, $ 2 et $ 3. Si vous ajoutez un autre support * parfois *, cela ne fonctionnera évidemment pas correctement. C'est pourquoi je dois le faire potentiellement sans crochets ... ou il doit y avoir un autre moyen. – Hasen

+0

Vous souhaitez obtenir une sous-chaîne depuis le début de la chaîne jusqu'à la correspondance, puis la correspondance, puis le texte après la correspondance? Attendez-vous un seul match dans une chaîne? –

Répondre

-3

Essayez ceci:

pattern=("/(.*)(\bIf [I|you]+ want\b)(.*)/iu"); 
+2

J'ai déjà essayé, mais les crochets ne fonctionnent pas comme ça. Essayez-le, cela ne fonctionne pas: regex101.com – Hasen

+0

Désolé voir la mise à jour de la réponse. Fonctionne sur http://regexr.com. J'ai raté le '+'. – DrRoach

+0

@Hasen Est-ce que ça marche avec le '+'? – DrRoach

-1

Pour tout correspondant à vous ou moi, cela a fonctionné pour moi:

$pattern=("/(.*)(\bIf (?:i|you) want\b)(.*)/iu"); 
+0

Je pense que les gens répondent juste trop rapidement. Le point entier de ma question est SANS parenthèses. Je ne sais pas si cela peut être fait ou non, mais j'ai déjà listé votre solution ici, dans ma question ... Je sais évidemment comment faire cela, mais l'ajout de crochets supplémentaires est ce qui cause le problème en premier lieu. – Hasen

+1

Mais ce n'est pas le support normal. Remarquez l'utilisateur de '?: I'. Cela rend cette parenthèse 'non-capturant des groupes de support' –

0

La question que vous avez est que vous ne pouvez pas compter sur les groupes de capture numérotés comme leur nombre peut varier puisque la partie de motif définie par l'utilisateur peut inclure un nombre arbitraire de groupes de capture numérotés.

Une sortie peut être via utilisant nommé groupes de capture. Le seul problème avec eux est que PHP ne supporte pas les références arrières nommées dans le modèle de remplacement. Il peut être contourné en utilisant la fonction preg_replace_callback:

$s = 'text If you want this'; 
echo preg_replace_callback("/(?<start>.*)(?<mid>If (I|you) want)(?<end>.*)/siu", function($m) { 
    return $m['start'].'*'.$m['mid'].'*'.$m['end']; 
}, $s); 
// => text *If you want* this 

Voir la PHP demo.

Vous pouvez "obscurcir" les noms de groupe afin qu'ils ne puissent pas entrer en conflit avec les modèles définis par l'utilisateur. Ou laissez les utilisateurs savoir quels noms ne peuvent pas être utilisés dans le motif.

Le modificateur s Note . fera également correspondre les sauts de ligne.

La solution ci-dessus correspondra à la dernière occurrence de mid groupe que le premier motif start est un motif de points gourmand. Si votre chaîne contient plusieurs correspondances et que vous souhaitez que le groupe mid corresponde à la première occurrence de la chaîne, remplacez (?<start>.*) par (?<start>.*?). Sinon, vous devez décider à quoi ressemblera l'algorithme.