Il y a deux jours, j'ai commencé à travailler sur un analyseur de code et je suis coincé.
Comment puis-je diviser une chaîne par des virgules qui ne sont pas des crochets, laissez-moi vous montrer ce que je veux dire: p>
J'ai cette chaîne à analyser: p> Je voudrais obtenir ce résultat: p> mais je reçois : P> array(
"one";
"two";
"three";
"(four";
"(five";
"six)";
"(ten))";
"seven"
)
7 Réponses :
J'ai peur que cela puisse être très difficile à analyser les crochets imbriqués comme
un, deux, (trois, (quatre, cinq)) code>
seulement avec regexp. p>
Vous ne pouvez pas, directement. Vous auriez besoin, au minimum, la largeur de la largeur variable et la dernière fois que je savais que le pcre de PHP n'a que la largeur de largeur fixe. P>
Ma première recommandation serait d'extraire d'abord des expressions parenthèses sur la chaîne. Je ne sais rien de votre problème réel, cependant, je ne sais pas si cela sera réalisable. P>
Oui, c'était le piratage que je prévoyais d'utiliser. Remplacez les supports avec 1 $, 2 $ ou quelque chose de similaire, divisez la chaîne et de restaurer les crochets dans le résultat. Merci !
Le point est que ce que vous décrivez n'est pas une langue régulière, les expressions régulières sont donc mal adaptées. Ainsi, analyser toutes les pièces imbriquées d'abord n'est pas un "hack" mais la chose la plus sensée à faire.
Je ne peux pas penser à un moyen de le faire en utilisant une seule regex, mais il est assez facile de bien pirater quelque chose qui fonctionne: Si vous l'invoquez comme ceci: p> it Sorties: p>
Merci beaucoup, cela devrait fonctionner. C'était comme ça que j'ai prévu de le faire en premier, mais je pensais qu'un moyen plus facile existe.
Votre méthode ne peut pas analyser "un, deux, trois, trois ((cinq), (quatre (six)), sept, huit, neuf". Je pense que la corrigue correcte serait une récursive: / ((([^ ()] + | (? R)) *) /.
Vous n'avez pas mentionné qu'il devait d'analyser les expressions récursives lorsque j'ai écrit cette réponse. Pourtant, d'autres ont certainement suggéré de meilleures solutions après avoir écrit cela.
maladroit, mais il fait le travail ...
<?php function split_by_commas($string) { preg_match_all("/\(.+?\)/", $string, $result); $problem_children = $result[0]; $i = 0; $temp = array(); foreach ($problem_children as $submatch) { $marker = '__'.$i++.'__'; $temp[$marker] = $submatch; $string = str_replace($submatch, $marker, $string); } $result = explode(",", $string); foreach ($result as $key => $item) { $item = trim($item); $result[$key] = isset($temp[$item])?$temp[$item]:$item; } return $result; } $test = "one, two, three, (four, five, six), seven, (eight, nine), ten"; print_r(split_by_commas($test)); ?>
hm ... ok déjà marqué comme répondu, mais comme vous avez demandé une solution facile, je vais essayer néanmoins: sortie p>
Merci beaucoup, votre aide est très appréciée. Mais maintenant, je me rends compte que je rencontrerai également des crochets imbriqués et que votre solution ne s'applique pas.
Vous pouvez le faire plus facile:
$str = 'one, two, three, (four, (five, six), (ten)), seven'; $buffer = ''; $stack = array(); $depth = 0; $len = strlen($str); for ($i=0; $i<$len; $i++) { $char = $str[$i]; switch ($char) { case '(': $depth++; break; case ',': if (!$depth) { if ($buffer !== '') { $stack[] = $buffer; $buffer = ''; } continue 2; } break; case ' ': if (!$depth) { continue 2; } break; case ')': if ($depth) { $depth--; } else { $stack[] = $buffer.$char; $buffer = ''; continue 2; } break; } $buffer .= $char; } if ($buffer !== '') { $stack[] = $buffer; } var_dump($stack);
Oui, c'est plus facile, mais ne fonctionne pas en cas de supports imbriqués, comme: un, deux, trois, (quatre, (cinq, six), (dix)), sept)
C'est le point où vous devez utiliser un réel analyseur. Les expressions régulières ne peuvent pas compter ou gérer les états.
Je dois utiliser des expressions régulières. Les expressions régulières sont récursives et gourmandes, vous pouvez y accomplir.
Non tu ne peux pas. Bien sûr, il existe des fonctionnalités dans des implémentations modernes pouvant accomplir ce type d'équilibrage i> i> (?
Celui-ci est plus correct, mais ne fonctionne toujours pas pour une parenthèse imbriquée / [^ (,] * (?: ([^)] +))? [^),] * /
Je pense que sa peine de noter que vous devriez toujours éviter les expressions régulières lorsque vous le pouvez éventuellement. À cette fin, vous devez savoir que pour PHP 5.3+, vous pouvez utiliser str_getcsv () . Toutefois, si vous travaillez avec des fichiers (ou des flux de fichiers), tels que des fichiers CSV, la fonction FgeCSV () pourrait être ce dont vous avez besoin, et c'est disponible depuis PHP4. P>
Enfin, je suis surpris que personne n'utilise Preg_split () , ou n'a-t-il pas fonctionné au besoin? P>
Oui Ken, je veux utiliser preg_split (), mais quelle serait la regex qui ignore les virgules entre parenthèses?
Ah oui, bon point, après avoir essayé un min ou 2, je peux voir que c'est difficile avec les conditions énoncées.
Ouais tu as raison, j'ai aussi essayé votre solution et ne fonctionne pas. Merci encore.