Как проверить, что vsprintf имеет правильное количество аргументов перед запуском - PullRequest
4 голосов
/ 13 января 2010

Я пытаюсь использовать vsprintf () для вывода отформатированной строки, но мне нужно проверить, что у меня есть правильное количество аргументов, прежде чем запускать ее, чтобы предотвратить ошибки "Too too arguments".

По сути, я думаю, что мне нужно регулярное выражение для подсчета количества спецификаторов типов, но я довольно бесполезен, когда дело доходит до регулярных выражений, и я не мог нигде его финансировать, поэтому я подумал, что бы ТАК попробовать , :)

Если вы не можете придумать лучшего способа, чтобы этот метод соответствовал тому, что я хочу.

function __insertVars($string, $vars = array()) {

    $regex = '';
    $total_req = count(preg_match($regex, $string));

    if($total_req === count($vars)) {
        return vsprintf($string, $vars);
    }

}

Пожалуйста, скажите мне, если вы можете придумать более простой способ.

Ответы [ 3 ]

5 голосов
/ 13 января 2010

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

Вот регулярное выражение, которое я придумал, используйте его с preg_match_all():

%[-+]?(?:[ 0]|['].)?[a]?\d*(?:[.]\d*)?[%bcdeEufFgGosxX]

На основании sprintf() документации . Должен быть совместим с PHP 4.0.6+ / 5 .


РЕДАКТИРОВАТЬ - немного более компактная версия:

%[-+]?(?:[ 0]|'.)?a?\d*(?:\.\d*)?[%bcdeEufFgGosxX]

Кроме того, используйте функции func_get_args() и func_num_args() в своем коде.


РЕДАКТИРОВАТЬ: - Обновлено для поддержки позиционных / перестановочных аргументов ( не проверено ):

function validatePrintf($format, $arguments)
{
    if (preg_match_all("~%(?:(\d+)[$])?[-+]?(?:[ 0]|['].)?(?:[-]?\d+)?(?:[.]\d+)?[%bcdeEufFgGosxX]~", $format, $expected) > 0)
    {
        $expected = intval(max($expected[1], count(array_unique($expected[1]))));

        if (count((array) $arguments) >= $expected)
        {
            return true;
        }
    }

    return false;
}

var_dump(validatePrintf('The %2$s contains %1$d monkeys', array(5, 'tree')));
0 голосов
/ 22 апреля 2019

Я думаю, что это очень просто, потому что возвращает ЛОЖНОЕ значение, если что-то не так. Вы можете проверить это так:

if (vsprintf($string, $wrongArray) === false) {
    // vsprintf has wrong number of arguments
}
0 голосов
/ 02 августа 2016

Я использовал ответ Аликс Аксель и создал универсальную функцию.

У нас есть $countArgs (из параметров функции) и $countVariables (из $format вроде %s).

Например:

$object->format('Hello, %s!', ['Foo']); // $countArgs = 1, $countVariables = 1;

Печать: Привет, Фу!

$object->format('Hello, %s! How are you, %s?', ['Bar']); // $countArgs = 1, $countVariables = 2;

Печать: ошибка.

Функция:

public static function format($format, array $args)
{
    $pattern = "~%(?:(\d+)[$])?[-+]?(?:[ 0]|['].)?(?:[-]?\d+)?(?:[.]\d+)?[%bcdeEufFgGosxX]~";

    $countArgs = count($args);
    preg_match_all($pattern, $format, $expected);
    $countVariables = isset($expected[0]) ? count($expected[0]) : 0;

    if ($countArgs !== $countVariables) {
        throw new \Exception('The number of arguments in the string does not match the number of arguments in a template.');
    } else {
        return $countArgs > 1 ? vsprintf($format, $args) : sprintf($format, reset($args));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...