11
votes

Analyser le texte brut de telle manière qui reconnaîtra une déclaration personnalisée si

J'ai la chaîne suivante: xxx

Je l'analyse en l'exécutant via la fonction suivante: xxx

où < Code> $ Num_Dogs est une variable prédéfinie. Selon $ num_dogs , cela pourrait renvoyer l'une des chaînes suivantes:

  • L'homme a 1 chiens.
  • L'homme a 2 chiens.
  • L'homme a 500 chiens.

    Le problème est que, dans le cas où "l'homme a 1 chiens", chien est pluralisé, non souhaité. Je sais que cela pourrait être résolu simplement en n'utilisant pas la fonction parse_text et à faire quelque chose comme: xxx

    mais dans ma demande, je fais une analyse plus que juste {num_dogs} et il faut beaucoup de lignes pour écrire toutes les conditions.

    J'ai besoin d'une manière abrégée que je peux écrire dans l'initiale $ string que je peux traverser un analyseur, ce qui ne me limiterait pas à seulement deux possibilités vraies / fausses.

    Par exemple, laissez xxx

    est-il clair ce qui s'est passé à la fin? Je suis tenté de lancer la création d'un tableau en utilisant la partie à l'intérieur des crochets qui est après la barre verticale, puis de comparer la clé du nouveau tableau avec la valeur analysable de {NUM_DOGS} (qui, par sera désormais la variable num_dogs $ à gauche de la barre verticale), et renvoie la valeur de l'entrée de tableau avec cette touche.

    Si ce n'est pas tout à fait déroutant, est-il possible à l'aide du preg_ * fonctions?


7 commentaires

Je reçois comment {NUM_DOGS} est transmis à la fonction, mais lorsque vous commencez à mentionner les noms de chiens, vous venez de me jeter complètement désactivé. Comment sont-ils passés à la fonction?


Si la chaîne est considérée comme super, super sûre. Cela peut très facilement être fait en utilisant eval php.net/manual /function.val.php


Ils ne sont pas transmis individuellement à la fonction, ils vont juste pour le trajet car ils sont contenus dans les $ string . Laissez $ num_dogs = 2 . Après avoir traversé parse_text $ string = L'homme a 2 [2 | 0 => "chiens", 1 => "chien appelé Fred", 2 => "Chiens appelés Fred and Harry" , 3 => "Chiens appelés Fred, Harry et Buster"].


meta.stackexchange.com/questions/9662/...


Windows utilise ce format parfois des fichiers. Peut-être chien (s) :)


@Ankush - Oui, ce serait adéquat si je n'avais que deux options, chiens ou chiens. Je veux montrer un message personnalisé pour chaque nombre de chiens.


Pouvez-vous avoir quelque chose comme 'l'homme a {num_dogs} {chiens}' , avec un autre str_replace pour {chiens} ?


4 Réponses :


6
votes

Tout d'abord, il est un peu discutable, mais si vous pouvez l'éviter facilement, passez simplement $ num_dogs code> comme argument à la fonction car la plupart des gens croient que les variables globales sont diaboliques!

Ensuite, pour obtenir le "S", je fais généralement quelque chose comme ceci: p> xxx pré>

puis fait quelque chose comme ceci: p>

switch $num_dogs {
    case 0:
        return 'dogs';
        break;
    case 1:
        return 'dog called fred';
        break;
    case 2:
        return 'dogs called fred and harry';
        break;
    case 3:
        return 'dogs called fred, harry and buster';
        break;
}


0 commentaires

12
votes

Le principe de votre question est que vous souhaitez match strong> un modèle spécifique fort>, puis remplacer fort> il après avoir effectué Traitement supplémentaire sur le texte assorti.

semble être un candidat idéal pour Preg_replace_callback Code> A > P>

Les expressions régulières de capture de parenthèses appariées, de citations, d'accolades, etc. peuvent devenir assez compliquées et tout faire avec une expression régulière est en fait assez inefficace. En fait, vous auriez besoin d'écrire un analyseur approprié si c'est ce dont vous avez besoin. P>

Pour cette question, je vais assumer un niveau de complexité limité et l'aborder avec une paquet de deux étapes à l'aide de Regex. P>


Tout d'abord, la plus simple regex que je puisse penser pour capturer des jetons entre les bretelles bouclées. p> xxx pré>

Permet de casser cela. xxx pré>

Lorsqu'il est appliqué à une chaîne avec preg_match_all code> Les résultats ressemblent à quelque chose comme: p> xxx pré>

looks bon jusqu'à présent. p>

Veuillez noter que si vous avez des bretelles imbriquées dans vos chaînes, c'est-à-dire {tok_two | 0 => "hi {x} y"} code>, cette regex ne sera pas travail. Si cela ne sera pas un problème, sautez à la section suivante. P>

Il est possible de faire une correspondance de haut niveau, mais la seule façon dont j'ai pu le faire est via la récursivité. La plupart des anciens combattants de Regex vous diront que dès que vous ajoutez de la récursivité à une regex, elle cesse d'être une regex. P>

C'est là que la complexité de traitement supplémentaire commence et avec de longues chaînes compliquées, il est très facile de courir hors de l'espace de pile et écrasez votre programme. Utilisez-le soigneusement si vous avez besoin de l'utiliser du tout. P>

la regex récursive extrait de l'une de mes autres réponses et modifié un peu. p> xxx pré>

décomposé. p> xxx pré>

et cette fois, la sortie de la sortie correspond à la page supérieure Bretelles de niveau P>

$string = preg_replace_callback('/{([^}]+)}/', function($match) use ($options) {
    $match = $match[1];

    if (false !== $pipe = strpos($match, '|')) {
        $tokens = substr($match, $pipe + 1);
        $match = substr($match, 0, $pipe);
    } else {
        $tokens = array();
    }

    if (isset($options[$match])) {
        if ($tokens) {
            preg_match_all('/(\d)+\s*=>\s*"([^"]*)",?/', $tokens, $tokens);

            $tokens = array_combine($tokens[1], $tokens[2]);

            return $tokens[$options[$match]];
        }
        return $options[$match];
    }
    return '';
}, $string);


1 commentaires

Pour des citations imbriquées, vous pouvez probablement facilement permettre à un caractère d'échappement (\ est traditionnel, bien sûr), sans avoir besoin d'une regex récursive. Ne fonctionnera cependant pas pour les accolades imbriquées.



6
votes

Dans une pincée, j'ai fait quelque chose de similaire à ce que vous demandez avec une implémentation vaguement comme le code ci-dessous.

Ceci n'est nulle part comme une caractéristique riche en tant que réponse @ Mike, mais cela a fait l'affaire dans le passé. xxx

Voici quelques exemples similaires à votre question originale ... xxx

La sortie est la suivante:

L'homme a 2 chiens.

L'homme a 1 chien.

Il peut être intéressant de mentionner que, dans des projets plus importants, j'ai invariablement terminé par la saisie de toute inflexion personnalisée en faveur de GNU GetText qui semble être la voie la plus saine une fois que la multi-linguelle est une exigence.


0 commentaires