Как изменить аргументы командной строки перед getopt ()

PHP getopt () не позволяет разделять аргумент и его необязательное значение пробелом, нужно либо разделять символом «=», либо не разделять:

# test.php uses getopt('a::')
> php test.php -a 3 // incorrect
> php test.php -a=3 // correct
> php test.php -a3 // correct

Но, с другой стороны, вы можете использовать пробел для разделения аргумента и его обязательного значения (которое указывается как getopt (‘a:’)). Ради последовательности и интуитивности использования пробелов я хотел бы исправить командную строку, прежде чем она будет обработана getopt () — у меня есть регулярное выражение, которое заменяет ‘-abc bc’ на ‘-abc = bc’.

Но оказывается, что изменение $ argv не влияет на getopt (). Я провел некоторое тестирование с помощью этого скрипта:

# t.php
<?php
var_dump($argv);
$argv = array();
var_dump($argv);
var_dump(getopt('a'));
?>

> php t.php -a

array(2) {
[0] =>
string(5) "t.php"[1] =>
string(2) "-a"}
array(0) {
}
array(1) {
'a' =>
bool(false)
}

Итак, был правильный $ argv, я переписал его в пустой массив и все еще getopt () действовал так, как будто ничего не произошло.

Вопросы:

  1. откуда getopt () получает свой вклад?
  2. как мне изменить этот ввод перед тем, как getopt () его проанализирует?

3

Решение

Глядя на исходный код PHP, кажется, что argc а также argv извлекаются непосредственно из движка Zend при вызове getoptТаким образом, изменение глобалов не повлияет на его поведение. Вы можете проверить исходный код для getopt Вот: https://github.com/php/php-src/blob/master/ext/standard/basic_functions.c#L4264.

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

1

Другие решения

Следуя комментарию Густаво, я отказался от getopt () и создал свой собственный анализатор. Это часть большей библиотеки кода, которую я не мог опубликовать здесь, потому что это слишком много кода. Я опубликую соответствующие методы, и я думаю, что вы сможете заполнить пробелы, если вам нужно такое решение:

public function parse()
{
$i = 1;
$max = count($GLOBALS['argv'])-1;
while ($i <= $max) {
// Disallow arguments like '---any', '--s' and '-long'
$argName = $this->getArgumentName($GLOBALS['argv'][$i]);
if ($argName !== false) {

// Allow only previously defined arguments
if (\array_key_exists($argName, $this->args)) {
// Disallow arguments with empty values like '-s ""'
if (($i < $max) && $GLOBALS['argv'][$i+1]=='') {
throw new SyntaxException("Empty values are not allowed", SyntaxException::BAD_SYNTAX);
}
// if argument without value then set it to true
elseif ($i == $max || ($this->getArgumentName($GLOBALS['argv'][$i+1]) !== false)) {
$this->args[$argName]->setValue(true);
$i++;
}
// if argument with value then assign it the value
else {
$this->args[$argName]->setValue($GLOBALS['argv'][$i+1]);
$i+=2;
}
} else throw new SyntaxException("Unexpected argument `$argName`", SyntaxException::UNEXPECTED_ARGUMENT);
} else throw new SyntaxException("Wrong syntax of `{$GLOBALS['argv'][$i][0]}` argument", SyntaxException::BAD_SYNTAX);
}

return $this;
}

protected function getArgumentName($str)
{
$name = \preg_replace('/(?:^-([\w\d])$)|(?:^--([\w\d][\w\d_?!.:-]+)$)/', '$1$2', $str,1);
if (\is_null($name)) {
throw new LogicException("Error in regexp with `$str` string");
}
return ($str == $name) ? false : $name;
}

О пробелах: эти исключения не из SPL, это моя пользовательская иерархия исключений. Я сделал это так, чтобы код исключения также был кодом возврата скрипта.
Кроме того, $ this-> args — это коллекция объектов типа Argument, способных содержать тип / поведение аргумента, имя, значение, валидаторы и тому подобное.

0

По вопросам рекламы [email protected]