2010-11-15 5 views
1

J'essaie d'utiliser regexp pour analyser une chaîne de recherche qui, de temps en temps, peut contenir une syntaxe spéciale. La syntaxe que je recherche est [mot-clé spécial: valeur] et je veux que chaque correspondance soit placée dans un tableau. Gardez à l'esprit que la chaîne de recherche contiendra d'autres textes qui ne sont pas destinés à être analysés.preg_match ne retourne pas les résultats attendus

$searchString = "[StartDate:2010-11-01][EndDate:2010-11-31]"; 
$specialKeywords = array(); 
preg_match("/\[{1}.+\:{1}.+\]{1}/", $searchString, $specialKeywords); 
var_dump($specialKeywords); 

sortie:

tableau

(1) {[0] => string (43) "[StartDate: 01/11/2010] [EndDate: 31/11/2010]"}

sortie désiré:

tableau

(2) {[0] => string() "[StartDate: 01/11/2010]"

[1] => string() "[EndDate: 2010-11-01]"}

S'il vous plaît laissez-moi savoir si je ne suis pas assez clair.

+1

Le quantificateur '{1} 'est inutile. – Gumbo

Répondre

4

Vos .+ matchs à travers les frontières entre les deux parties [...] parce qu'elle correspond à un caractère, et le plus grand nombre possible d'entre eux. Vous pourriez être plus restrictif quant aux caractères qui peuvent être appariés. De plus, {1} est redondant et peut être supprimé.

/\[[^:]*:[^\]]*\]/ 

devrait fonctionner de manière plus fiable.

Explication:

\[  # match a [ 
[^:]* # match any number of characters except : 
:  # match a : 
[^\]]* # match any number of characters except ] 
\]  # match a ] 
+0

Merci cela a fonctionné parfaitement, j'ai dû utiliser le preg_match_all pour obtenir le tableau construit correctement, mais l'expression était sur place. Merci encore –

+0

Pouvez-vous entrer dans un peu plus de détail dans l'explication. Je suis confus comment '[^:] *' = 'correspond à n'importe quel nombre de caractères sauf:'.Est-ce que '[^:] *' fait correspondre tous les caractères jusqu'à ': 'parce que': 'est dans l'expression rationnelle? –

+0

@Derek Adair: Le '[^:] *' correspond à autant de caractères non-':' que possible, donc il correspond à tous les caractères jusqu'à (mais n'incluant pas) ':'. Ce comportement est indépendant de la présence ou non d'un ':' dans l'expression rationnelle - mais bien sûr, cela a du sens ici. Il permet également de faire correspondre le plus rapidement possible car le moteur regex n'a jamais besoin de revenir en arrière. –

1

les opérations suivantes:

$searchString = "[StartDate:2010-11-01][EndDate:2010-11-31]"; 
$specialKeywords = array(); 
preg_match_all("/\[\w+:\d{4}-\d\d-\d\d\]/i", $searchString, $specialKeywords); 

var_dump($specialKeywords[0]); 

Sorties:

array(2) { 
    [0]=> 
    string(22) "[StartDate:2010-11-01]" 
    [1]=> 
    string(20) "[EndDate:2010-11-31]" 
} 
+0

Il a besoin de date de début/fin, pas 2 dates de fin – Webnet

+0

@Webnet Yeeea, je devrais vraiment * regarder * à la sortie avant de le copier/coller dans une réponse. – meagar

+0

Merci pour la réponse, le problème que je vois avec l'expression que vous avez fournie est que la valeur ne sera pas toujours au format Y-m-d. –

1

Ce:

$searchString = "[StartDate:2010-11-01][EndDate:2010-11-31]"; 
preg_match_all('/\[.*?\]/', $searchString, $match); 

print_r($match); 

donne le résultat attendu, je ne sais pas si elle correspond à toutes les contraintes.

+0

Merci pour la réponse, le preg_match_all était un composant manquant mais l'expression d'une autre réponse était plus proche de ce que je cherchais. –

0

Utilisez cette regex: "/\[(.*?)\:(.*?)\]{1}/" et également utiliser preg_match_all, il retournera

array(3) { 
    [0]=> 
    array(2) { 
    [0]=> 
    string(22) "[StartDate:2010-11-01]" 
    [1]=> 
    string(20) "[EndDate:2010-11-31]" 
    } 
    [1]=> 
    array(2) { 
    [0]=> 
    string(9) "StartDate" 
    [1]=> 
    string(7) "EndDate" 
    } 
    [2]=> 
    array(2) { 
    [0]=> 
    string(10) "2010-11-01" 
    [1]=> 
    string(10) "2010-11-31" 
    } 
} 
0
/\[.+?\:.+?\]/ 

Je suggère cette méthode, moins complexe, mais il gère les mêmes que

tim
Questions connexes