2009-04-28 8 views
2

J'ai cette chaîne en PHP:chaîne php analyser avec regard vers l'avenir

$string = "name=Shake & Bake&difficulty=easy"; 

Pour que je veux analyser dans un tableau:

Array 
(
    [name] => Shake & Bake 
    [difficulty] => easy 
) 

PAS:

Array 
(
    [name] => Shake 
    [difficulty] => easy 
) 

Qu'est-ce le moyen le plus efficace de le faire?

+0

il est standard de citer esperluette devrait être cité comme &. Ne pas le faire vous causera des maux de tête importants. –

+0

Voir ma solution mise à jour. – cletus

Répondre

4

Il y a probablement un moyen plus efficace de le faire, mais essayez

$foo = 'name=Shake & Bake&difficulty=easy'; 
$pairs = preg_split('{&(?=[^\s])}',$foo); 
//$pairs = preg_split('/&(?=[^\s])/',$foo); //equivalent, using different delimiters. 
//$pairs = preg_split('%&(?=[^\s])%',$foo); //equivalent, using different delimiters. 
$done = Array(); 
foreach($pairs as $keyvalue){ 
    $parts = preg_split('{=}',$keyvalue); 
    $done[$parts[0]] = $parts[1]; 
} 
print_r($done); 

moteur regex PHP est PCRE, et il soutient regarder vers l'avenir affirmations. Googling autour de PCRE, PHP, RegEx, anticiper les assertions et les affirmations de largeur nulle devrait vous donner plus que vous voulez jamais savoir sur le sujet.

+0

pourriez-vous expliquer la signification des accolades. À ma connaissance, ils doivent spécifier la répétition. – bob

+0

Le module PCRE de PHP utilise des "délimiteurs" sur ses expressions. Traditionnellement, la barre oblique est utilisée, mais Alan utilise ici des accolades correspondantes. Les expressions ici pourraient aussi avoir été écrites '/ & (? = [^ \ S]) /' et '/ = /'. –

+0

Désolé Bob, c'est une vieille bizarrerie à moi. PCRE crée/permet de mettre des caractères délimiteurs autour des expressions régulières, il permet d'inclure des modificateurs de pattern directement après l'expression, style perl./like this/six Ils sont habituellement des barres obliques, mais quand j'ai commencé à pirater des reg, c'était pour passer en HTML, donc j'ai trouvé plus facile de choisir un délimiteur différent car j'avais toujours besoin d'un "/" pour le motif et ne voulait pas y échapper. J'ai choisi "{}", ce qui n'était probablement pas le meilleur car ceux-ci sont utilisés pour la répétition dans une expression. Désolé de vous confondre. –

3

expressions régulières semble être la meilleure façon de le faire.

<html> 
<head> 
    <title>Test params</title> 
</head> 
<body> 
<?php 
test_build('a=b'); 
test_build('blah=foo&foo=foo2'); 
test_build('blah=foo&foo&foo2=foo3&foo'); 

function test_build($string) { 
    echo "<p>Testing: $string</p>\n"; 
    $params = build_params($string); 
    if ($params) { 
    echo "<ul>\n"; 
    foreach ($params as $k => $v) { 
     echo "<li>'$k' => '$v'</li>\n"; 
    } 
    echo "</ul>\n"; 
    } else { 
    echo "<p>Found no parameters.</p>\n"; 
    } 
} 

function build_params($string) { 
    preg_match_all('!([^=&]+)=([^=]*)(?=(&|$))!', $string, $matches); 
    $ret = array(); 
    for ($i=0; $i<sizeof($matches[1]); $i++) { 
    $ret[$matches[1][$i]] = $matches[2][$i]; 
    } 
    return $ret; 
} 
?> 
</body> 
</html> 

Sortie:

Testing: a=b 

    * 'a' => 'b' 

Testing: blah=foo&foo=foo2 

    * 'blah' => 'foo' 
    * 'foo' => 'foo2' 

Testing: blah=foo&foo&foo2=foo3&foo 

    * 'blah' => 'foo&foo' 
    * 'foo2' => 'foo3&foo' 
+0

Mon hypothèse est que vous pouvez vous retrouver avec un & dans la valeur, mais pas la clé. – bob

+0

Comme blah = foo & foo & blah2 = foo devrait être {'blah' => 'foo & foo', 'blah2' => 'foo'}? Si c'est un peu plus compliqué. – cletus

+0

oui, bla = foo & foo & blah2 = foo doit être { 'bla' => 'foo & foo', 'blah2' => 'foo'} – bob

0

La fonction parse_str() fait exactement ce dont vous avez besoin - assurez-vous juste, vous passez le deuxième paramètre pour des raisons de sécurité évidentes. Vous devez traduire votre chaîne d'entrée, bien que:

$string = "name=Shake & Bake&difficulty=easy"; 
parse_str(str_replace(' & ', '+%26+', $string), $array); 
+0

Je suis sûr que "name = Shake & Bake & difficulté = easy" échouera. Les espaces étaient là pour mettre en évidence ne pas suggérer le format. – jmucchiello

+0

Ensuite, vous pouvez ajouter des clés avec des valeurs vides dans le tableau résultant à la clé précédente.Je vais mettre à jour la réponse – soulmerge

+0

Je viens de remarquer que cela transformerait des choses urlencodées (% 48 => a), ce qui n'est peut-être pas ce que vous voulez, je laisserai la réponse telle qu'elle était. – soulmerge

1

<?php 
$pattern ='/([^&]+)=([^=]+)(?=$|&[^=]+=)/';
$test = array( 'name=Shake & Bake&difficulty=easy', 'name=Shake&Bake&difficulty=easy', 'difficulty=easy&name=Shake & Bake', 'difficulty=easy&name=Shake&Bake', 'name=Shake&Bake', 'difficulty=easy', 'name=Shake&Bake&foo&difficulty=easy', 'name=Shake&Bake&difficulty=easy&', 'name=Shake&Bake&difficulty=' ); foreach($test as $foo) { preg_match_all($pattern, $foo, $m); echo $foo, "\n"; for($i=0; $i<count($m[0]); $i++) { echo ' ', $m[1][$i], ' =$gt; "', $m[2][$i], "\"\n"; } echo "\n"; } ?>
produit
name=Shake & Bake&difficulty=easy 
    name => "Shake & Bake" 
    difficulty => "easy"
name=Shake&Bake&difficulty=easy name => "Shake&Bake" difficulty => "easy"
difficulty=easy&name=Shake & Bake difficulty => "easy" name => "Shake & Bake"
difficulty=easy&name=Shake&Bake difficulty => "easy" name => "Shake&Bake"
name=Shake&Bake name => "Shake&Bake"
difficulty=easy difficulty => "easy"
name=Shake&Bake&foo&difficulty=easy name => "Shake&Bake&foo" difficulty => "easy"
name=Shake&Bake&difficulty=easy& name => "Shake&Bake" difficulty => "easy&"
name=Shake&Bake&difficulty= name => "Shake&Bake"
qui semble fonctionner (sauf difficulté = pas adaptée dans le dernier exemple).
Je ne suis pas sûr qu'une correspondance de sous-masque unique améliore la vitesse. Vous pourriez vouloir regarder ceci.

-1

urlencode() le & dans "Shake & Faire cuire" et utiliser (parse_str)