После использования PHP getopt(), как я могу определить, какие аргументы остаются?
ОК, поэтому у PHP есть встроенная функция getopt(), которая возвращает информацию о том, какие параметры программы предоставил пользователь. Только, если я что-то не упустил, он полностью разорвался! Из руководства:
Анализ синтаксического разбора завершится с первой найденной опцией, все последующее отброшено.
Итак, getopt()
возвращает массив только с действительными и разборными параметрами. Вы все еще можете увидеть всю исходную командную строку, посмотрев на $argv
, которая остается неизменной, но как вы определяете, где в этой командной строке getopt()
перестали разбираться в аргументах? Очень важно знать это, если вы хотите рассматривать остальную часть командной строки как другой материал (например, имена файлов).
Вот пример...
Предположим, что я хочу настроить script для принятия следующих аргументов:
Usage: test [OPTION]... [FILE]...
Options:
-a something
-b something
-c something
Тогда я мог бы называть getopt()
следующим образом:
$args = getopt( 'abc' );
И, если я запустил script следующим образом:
$ ./test.php -a -bccc file1 file2 file3
Я должен ожидать, что для меня вернется следующий массив:
Array
(
[a] =>
[b] =>
[c] => Array
(
[0] =>
[1] =>
[2] =>
)
)
Итак, вопрос заключается в следующем: как на Земле я должен был знать, что три аргумента без аргумента, без опций FILE
начинаются с $argv[ 3 ]
???
Ответы
Ответ 1
Начиная с PHP 7.1, getopt
поддерживает необязательный параметр ref-ref, &$optind
, который содержит индекс, где аргумент parsing остановлен. Это полезно для смешивания флагов с позиционными аргументами. Например:.
[email protected]:~$ php -r '$i = 0; getopt("a:b:", [], $i); print_r(array_slice($argv, $i));' -- -a 1 -b 2 hello1 hello2
Array
(
[0] => hello1
[1] => hello2
)
Ответ 2
Никто не сказал, что вы не используете getopt. Вы можете сделать это любым способом:
$arg_a = null; // -a=YOUR_OPTION_A_VALUE
$arg_b = null; // -b=YOUR_OPTION_A_VALUE
$arg_c = null; // -c=YOUR_OPTION_A_VALUE
$arg_file = null; // -file=YOUR_OPTION_FILE_VALUE
foreach ( $argv as $arg )
{
unset( $matches );
if ( preg_match( '/^-a=(.*)$/', $arg, $matches ) )
{
$arg_a = $matches[1];
}
else if ( preg_match( '/^-b=(.*)$/', $arg, $matches ) )
{
$arg_b = $matches[1];
}
else if ( preg_match( '/^-c=(.*)$/', $arg, $matches ) )
{
$arg_c = $matches[1];
}
else if ( preg_match( '/^-file=(.*)$/', $arg, $matches ) )
{
$arg_file = $matches[1];
}
else
{
// all the unrecognized stuff
}
}//foreach
if ( $arg_a === null ) { /* missing a - do sth here */ }
if ( $arg_b === null ) { /* missing b - do sth here */ }
if ( $arg_c === null ) { /* missing c - do sth here */ }
if ( $arg_file === null ) { /* missing file - do sth here */ }
echo "a=[$arg_a]\n";
echo "b=[$arg_b]\n";
echo "c=[$arg_c]\n";
echo "file=[$arg_file]\n";
Я всегда так делаю, и это работает. Более того, я могу делать все, что захочу.
Ответ 3
Для получения любых аргументов, следующих за параметрами командной строки, можно использовать следующие.
Он может использоваться до или после вызова PHP getopt()
без изменения результата:
# $options = getopt('cdeh');
$argx = 0;
while (++$argx < $argc && preg_match('/^-/', $argv[$argx])); # (no loop body)
$arguments = array_slice($argv, $argx);
$arguments
теперь содержит любые аргументы, следующие за любыми ведущими опциями.
В качестве альтернативы, если вы не хотите аргумент в отдельном массиве, то $argx
является индексом первого фактического аргумента: $argv[$argx]
.
Если аргументов нет, после каких-либо ведущих опций:
-
$arguments
- пустой массив []
и
-
count($arguments) == 0
и
-
$argx == $argc
.
Ответ 4
Взгляните на GetOptionKit, чтобы избавиться от разбора флага.
http://github.com/c9s/GetOptionKit
GetOptionKit может быть легко интегрирован в вашу командную строку script. Он поддерживает ограничение типов, валидацию значений и т.д.