Как я могу проверить регулярное выражение?

Я бы хотел проверить правильность регулярного выражения в PHP, желательно до его использования. Единственный способ сделать это на самом деле пытается preg_match() и посмотреть, вернет ли он FALSE?

Существует ли более простой/правильный способ проверки правильного регулярного выражения?

Ответ 1

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

Как сказал пользователь pozs, также рассмотрите возможность размещения @ перед preg_match() (@preg_match()) в тестовой среде для предотвращения предупреждений или уведомлений.

Чтобы проверить, что RegExp запускает его только с помощью null (вам не нужно знать данные, которые вы хотите протестировать против upfront). Если он возвращает явное ложное (=== false), оно прерывается. В противном случае он действителен, хотя ему ничего не нужно.

Поэтому нет необходимости писать свой собственный валидатор RegExp. Впустую время...

Ответ 2

Я создал простую функцию, которую можно вызвать для проверки preg

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()];
}

Вы можете вызвать эту функцию, используя следующий код:

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

Альтернатива - Онлайн-тестер регулярных выражений

Ответ 3

Если вы хотите динамически протестировать регулярное выражение preg_match(...) === false, кажется, ваш единственный вариант. PHP не имеет механизма для компиляции регулярных выражений до их использования.

Также вы можете найти preg_last_error полезную функцию.

С другой стороны, если у вас есть регулярное выражение и просто хочу знать, действительно ли он действителен перед его использованием, есть множество инструментов, доступных там. Я нашел rubular.com, чтобы быть приятным в использовании.

Ответ 4

Вы можете проверить, является ли это синтаксически правильным регулярным выражением с этим кошмаром регулярного выражения, если ваш движок поддерживает рекурсию (PHP должен).

Вы не можете, как бы алгоритмически не сказать, даст ли он желаемые результаты без его запуска.

От: Существует ли регулярное выражение для определения правильного регулярного выражения?

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

Ответ 5

Без выполнения регулярного выражения вы не можете быть уверены, что он действителен. Недавно я реализовал аналогичный RegexValidator для Zend Framework. Работает нормально.

<?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;
    }
}

Ответ 6

Вы можете проверить правильное выражение с помощью регулярного выражения и до определенного предела. Ознакомьтесь с этим ответом на переполнение стека для получения дополнительной информации.

Примечание: "рекурсивное регулярное выражение" не является регулярным выражением, и эта расширенная версия регулярного выражения не соответствует расширенным регулярным выражениям.

Лучше использовать preg_match и сопоставлять с NULL как @Claudrian сказал

Ответ 7

Итак, для всех, кто подходит к этому вопросу, вы можете проверять регулярные выражения в PHP с помощью такой функции.

preg_match() возвращает 1, если шаблон соответствует заданному объекту, 0, если это не так, или FALSE, если произошла ошибка. - Руководство по PHP

/**
 * Return an error message if the regular expression is invalid
 *
 * @param string $regex string to validate
 * @return string
 */
function invalidRegex($regex)
{
    if(preg_match($regex, null) !== false)
    {
        return '';
    }

    $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()];
}

Что можно использовать как это.

if($error = invalidRegex('/foo//'))
{
    die($error);
}

Ответ 9

Я бы склонен настраивать несколько модульных тестов для вашего регулярного выражения. Таким образом вы не только сможете убедиться, что регулярное выражение действительно действительно, но также эффективно при сопоставлении.

Я нахожу, что использование TDD - эффективный способ разработки регулярного выражения и означает, что его расширение в будущем упрощается, поскольку у вас уже есть все имеющиеся тестовые примеры.

Ответ на этот вопрос дает отличный ответ на настройку модульных тестов.

Ответ 10

Вы должны попытаться сопоставить регулярное выражение с NULL.

В PHP> = 5.5 вы можете использовать следующее для автоматического получения встроенного сообщения об ошибке, без необходимости определять собственную функцию для его получения:

preg_match($regex, NULL);
echo array_flip(get_defined_constants(true)['pcre'])[preg_last_error()];

Ответ 11

В соответствии с ссылкой PCRE, нет такого способа проверить достоверность выражения, до, который он использовал, Но я думаю, что если кто-то использует недопустимое выражение, это ошибка дизайна в этом приложении, а не во время выполнения, поэтому вы должны быть в порядке.