2011-01-10 2 views
3

Regex est absolument mon point faible et celui-ci m'a complètement perplexe. Je construis une fonctionnalité de recherche assez basique et je dois être en mesure de modifier mon entrée utilisateur en fonction du schéma suivant:Utiliser preg_replace pour remplacer toutes les occurrences dans php

Objet:

%22first set%22 %22second set%22-drupal -wordpress 

sortie souhaitée:

+"first set" +"second set" -drupal -wordpress 

Je souhaite Je pourrais être plus utile car normalement je veux au moins poster la solution que j'ai jusqu'ici, mais sur celle-ci je suis perdue.

Toute aide est appréciée. Je vous remercie.

+1

Il semble que vos données sont codées URL. Si vous appliquez [urldecode] (http://php.net/manual/en/function.urldecode.php), vous obtiendrez '' first set '' second set '-drupal -wordpress'. Avez-vous réellement un espace avant '-drupal' ou devrait-il être inséré aussi? –

+0

Je peux gérer l'espace. Le seul problème utilisant urldecode est que cela se passe dans une requête sql et je veux seulement urduecode guillemets doubles et seulement si elles sont dans ce modèle. – S16

Répondre

1
preg_replace('/%22((?:[^%]|%[^2]|%2[^2])*)%22/', '+"$1"', $str); 

Explication: Le $1 est une référence arrière, qui fait référence à la première () -section dans l'expression régulière, dans ce cas, ((?:[^%]|%[^2]|%2[^2])*). Et le [^%] et les alternances (...|...|...) après il empêche %22 entre être apparié en raison de la gourmandise. Voir http://en.wikipedia.org/wiki/Regular_expression#Lazy_quantification.

Je trouve cette technique dans un exemple JavaCC des commentaires de bloc correspondant (/* */), et je ne peux pas trouver d'autres pages Web expliquant, alors voici un exemple plus propre: Pour correspondre à un bloc de texte entre 12 345 12345........12345 sans 12345 entre: /12345([^1]|1[^2]|12[^3]|123[^4]|1234[^5])*12345/

+1

Vous rock. Merci beaucoup. Avez-vous une chance d'offrir une explication sur la solution? – S16

+0

Le '$ 1' est une référence arrière, qui fait référence à la première section'() 'dans l'expression régulière, dans ce cas,' ((?: [^%] |% [^ 2] |% 2 [^ 2]) *) '. Et la chose '[^%]' empêche que% 22 soit mis en correspondance: empêche l'appariement gourmand, la gourmandise est expliquée dans http://en.wikipedia.org/wiki/Regular_expression#Lazy_quantification, tandis que le '[^%]' La méthode est expliquée dans http: // shinkirou.org/blog/2010/12/tricky-regular-expression-problems/(vu d'abord dans un exemple JavaCC) –

+0

@SHiNKiROU Explication à un code donné en réponse, devrait être mis à ** répondre à itsef **, pas aux commentaires , où beaucoup de gens peuvent le manquer. Je me demande, pourquoi n'avez-vous pas édité votre propre réponse, lorsqu'on vous a demandé une clarification, et utilisé un petit commentaire à la place? – trejder

2

Semble que vos données sont codées en URL. Si vous appliquez urldecode, vous obtiendrez

"first set" "second set" -drupal -wordpress 

(Je suppose que vous avez un espace avant -drupal).

Maintenant, vous devez ajouter +. Encore une fois, je suppose que vous devez ajouter les avant tous les mots qui n'ont pas de - et qui ne sont pas entre guillemets:

$str = '"first set" "second set" -drupal -wordpress foo'; 
echo preg_replace('#(|^)(?!(?:\w+"|-|))#','\1+', $str)); 
// prints +"first set" +"second set" -drupal -wordpress +foo 

Mise à jour: Si vous ne pouvez pas utiliser urldecode, vous pouvez simplement utiliser str_replace pour remplacer %22 avec ".

1

Est-ce ce que vous cherchez?

<?php 
    $input = "%22first set%22 %22second set%22-drupal -wordpress"; 
    $res = preg_replace("/\%22(.+?)\%22/","+\"(\\1)\" ", $input); 
    print $res; 
?> 
+0

Explication: la correspondance \% 22 "% 22". La clé ici est la partie (. +?), Qui trouve la correspondance la plus courte (c'est-à-dire, "ungreedy") entre les% 22s. Dans la deuxième partie, \ 1 représente la valeur correspondante dans (. +?). – phooji

Questions connexes