77 votes

Comment valider une expression rationnelle ?

J'aimerais tester la validité d'une expression régulière en PHP, de préférence avant qu'elle ne soit utilisée. La seule façon de le faire est-elle d'essayer une expression régulière de type preg_match() et voir si elle renvoie FALSE ?

Existe-t-il un moyen plus simple/approprié de vérifier la validité d'une expression régulière ?

7 votes

Voulez-vous dire quelque chose comme : stackoverflow.com/questions/172303/ ?

0 votes

Si cela ne doit pas être en code, vous pouvez aller sur regexr.com, et coller votre regex, et taper le texte contre lequel vous le faites correspondre.

0 votes

Pourquoi ne voulez-vous pas vérifier preg_match() contre false ?

146voto

CodeAngry Points 5672
// This is valid, both opening ( and closing )
var_dump(preg_match('~Valid(Regular)Expression~', '') === false);
// This is invalid, no opening ( for the closing )
var_dump(preg_match('~InvalidRegular)Expression~', '') === false);

Comme l'utilisateur pozs a dit, aussi envisager de mettre @ devant preg_match() ( @preg_match() ) dans un environnement de test pour éviter les avertissements ou les avis.

Pour valider une RegExp, il suffit de l'exécuter contre null (il n'est pas nécessaire de connaître à l'avance les données contre lesquelles vous voulez tester) . S'il renvoie un faux explicite ( === false ), il est cassé. Sinon, il est valide bien qu'il ne doive pas nécessairement correspondre à quoi que ce soit.

Il n'est donc pas nécessaire d'écrire votre propre validateur RegExp. C'est une perte de temps...

1 votes

Juste une supposition : L'OP a dit "Je voudrais tester la validité d'une expression régulière en PHP, de préférence avant de l'utiliser. "

7 votes

@Cyborgx37 Et alors ? Je lui ai donné la solution avec un NULL. Tu n'as pas besoin de connaître la chaîne contre laquelle tu vas l'utiliser. Tu as juste besoin de connaître le modèle pour voir s'il est correct. Si ça correspond ou pas... c'est une autre histoire et ça dépend de la chaîne cible. Qu'est-ce que j'ai dit de mal ?

1 votes

Je ne t'ai pas déclassé... je devine juste pourquoi quelqu'un aurait pu le faire. Je pense que ta réponse est bonne.

25voto

Wahyu Kristianto Points 1634

J'ai créé une fonction simple qui peut être appelée pour vérifier la prévalence.

function is_preg_error()
{
    $errors = array(
        PREG_NO_ERROR               => 'Code 0 : No errors',
        PREG_INTERNAL_ERROR         => 'Code 1 : There was an internal PCRE error',
        PREG_BACKTRACK_LIMIT_ERROR  => 'Code 2 : Backtrack limit was exhausted',
        PREG_RECURSION_LIMIT_ERROR  => 'Code 3 : Recursion limit was exhausted',
        PREG_BAD_UTF8_ERROR         => 'Code 4 : The offset didn\'t correspond to the begin of a valid UTF-8 code point',
        PREG_BAD_UTF8_OFFSET_ERROR  => 'Code 5 : Malformed UTF-8 data',
    );

    return $errors[preg_last_error()];
}

Vous pouvez appeler cette fonction en utilisant le code suivant :

preg_match('/(?:\D+|<\d+>)*[!?]/', 'foobar foobar foobar');
echo is_preg_error();

Alternative - Testeur en ligne d'expressions régulières

2 votes

C'est juste une enveloppe autour de preg_last_error spécifique pour la langue anglaise.

0 votes

À propos, cela ne vous permettra pas vraiment de savoir si une expression rationnelle est valide ou non. Considérez ceci : php > preg_match("/aaa","") ; php > echo preg_last_error() ; 0

0 votes

Ajout de PHP 7 PREG_JIT_STACKLIMIT_ERROR . Voir le docs .

15voto

Alin Purcaru Points 21373

Si vous voulez tester dynamiquement une regex preg_match(...) === false semble être votre seule option. PHP n'a pas de mécanisme pour compiler les expressions régulières avant qu'elles ne soient utilisées.

Vous pouvez également trouver preg_last_error une fonction utile.

D'autre part, si vous avez une expression rationnelle et que vous souhaitez simplement savoir si elle est valide avant de l'utiliser, il existe un grand nombre d'outils disponibles. J'ai trouvé rubular.com d'être agréable à utiliser.

6voto

evandentremont Points 752

Vous pouvez vérifier si c'est une regex syntaxiquement correcte avec ce cauchemar de regex, si votre moteur supporte la récursion (PHP devrait).

Vous ne pouvez cependant pas dire de manière algorithmique si elle donnera les résultats que vous souhaitez sans l'exécuter.

De : Existe-t-il une expression régulière permettant de détecter une expression régulière valide ?

/^((?:(?:[^?+*{}()[\]\\|]+|\\.|\[(?:\^?\\.|\^[^\\]|[^\\^])(?:[^\]\\]+|\\.)*\]|\((?:\?[:=!]|\?<[=!]|\?>)?(?1)??\)|\(\?(?:R|[+-]?\d+)\))(?:(?:[?+*]|\{\d+(?:,\d*)?\})[?+]?)?|\|)*)$/

0 votes

Cela ne peut certainement pas fonctionner dans le cas général ?

0 votes

Cette regex est récursive. Ce n'est donc pas une regex au sens classique du terme, mais elle fonctionne dans les moteurs d'expressions régulières compatibles Perl.

2voto

ChrisR Points 8814

Sans exécuter réellement l'expression rationnelle, vous n'avez aucun moyen de savoir si elle est valide. J'ai récemment implémenté un RegexValidator similaire pour Zend Framework. Il fonctionne très bien.

<?php
class Nuke_Validate_RegEx extends Zend_Validate_Abstract
{
    /**
     * Error constant
     */
    const ERROR_INVALID_REGEX = 'invalidRegex';

    /**
     * Error messages
     * @var array
     */
    protected $_messageTemplates = array(
        self::ERROR_INVALID_REGEX => "This is a regular expression PHP cannot parse.");

    /**
     * Runs the actual validation
     * @param string $pattern The regular expression we are testing
     * @return bool
     */
    public function isValid($pattern)
    {
        if (@preg_match($pattern, "Lorem ipsum") === false) {
            $this->_error(self::ERROR_INVALID_REGEX);
            return false;
        }
        return true;
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X