Help us understand the problem. What is going on with this article?

phpでコマンドラインスクリプトのオプション制御

More than 1 year has passed since last update.

$argv

特に説明は無いマニュアルどおり
$argv

cmd.php
#!/usr/local/bin/php -q
<?php
var_dump($argv);

実行

./cmd.php aaa bbb ccc -ddd -eee
array(6) {
  [0]=>
  string(9) "./cmd.php"
  [1]=>
  string(3) "aaa"
  [2]=>
  string(3) "bbb"
  [3]=>
  string(3) "ccc"
  [4]=>
  string(2) "-d"
  [5]=>
  string(5) "--eee"
}

getopt

bashのgetoptと思うとかなり劣化版(想定外のオプションの制御が効かないなど)だけど人力$argvを解析するより遥かにマシ
ガッチリ組むならPEAR::Console_CommandLineが良い
→解説は「コマンドラインの引数解析を簡単に!」が親切

commander.php
#!/usr/local/bin/php -q
<?php
//[-h]など一文字で制御する方法
$shortopts = 'h';//スイッチだけ
$shortopts .= 'a:';//:は値を必須で受け取る
$shortopts .= 'b::';//::は値を任意に受け取る
$shortopts .= 'c:';//:は値を必須で受け取る

//([--help]など長名で制御する方法)
$longopts[] = 'help';//スイッチだけ
$longopts[] = 'aaa:';//:は値を必須で受け取る
$longopts[] = 'bbb::';//::は値を任意に受け取る
$longopts[] = 'ddd::';//::は値を任意に受け取る

$options = getopt($shortopts, $longopts);
if($options === false){
  fputs(STDERR, "There was a problem reading in the options.\n" . print_r($argv, true));
  exit(1);
}
$output='';

if(isset($options['h']) || isset($options['help'])){
  $output =<<<'EOL'
-h [--help]  helpこのコマンド
-a [--aaa]   あああ
-b [--bbb]   ビビビ
-c           シシシ
--ddd        デデデ

EOL;
  echo $output;
  exit(0);
}

var_dump($options);

実行

$ ./commander.php -h
-h [--help]  helpこのコマンド
-a [--aaa]   あああ
-b [--bbb]   ビビビ
-c           シシシ
--ddd        デデデ

$ ./commander.php --help
-h [--help]  helpこのコマンド
-a [--aaa]   あああ
-b [--bbb]   ビビビ
-c           シシシ
--ddd        デデデ
#一般的なヘルプ

$ ./commander.php -a
array(0) {
}
#↑値が無いがないので空

$ ./commander.php -a ZZZ
array(1) {
  ["a"]=>
  string(3) "ZZZ"
}

$ ./commander.php -aZZZ
array(1) {
  ["a"]=>
  string(3) "ZZZ"
}

$ ./commander.php -a=ZZZ
array(1) {
  ["a"]=>
  string(3) "ZZZ"
}

#↑値の入力はスペース区切り、続けて入力、=区切りで可能

$ ./commander.php -a X -a=Y -aZ
array(1) {
  ["a"]=>
  array(3) {
    [0]=>
    string(1) "X"
    [1]=>
    string(1) "Y"
    [2]=>
    string(1) "Z"
  }
}
#複数の値を受け付けられる

#但し↓のように必須optに引数を与え無いと、後続が引数扱いになる
$ ./commander.php -a -b=XXX
array(1) {
  ["a"]=>
  string(6) "-b=XXX"
}

$ ./commander.php -a= -bXXX --aaa= -bYYY
array(2) {
  ["a"]=>
  string(0) ""
  ["b"]=>
  array(2) {
    [0]=>
    string(3) "XXX"
    [1]=>
    string(3) "YYY"
  }
}
#値指定に `=` を使えば回避できそうだが単optに=をつけると空文字が入る

#↓任意optの場合は正しく解析できる
$ ./commander.php -b -a=XXX
array(2) {
  ["b"]=>
  bool(false)
  ["a"]=>
  string(3) "XXX"
}



$ ./commander.php --aaa=XXX --aaaYYY --aaa ZZZ -c " " --ddd
array(3) {
  ["aaa"]=>
  array(2) {
    [0]=>
    string(3) "XXX"
    [1]=>
    string(3) "ZZZ"
  }
  ["c"]=>
  string(1) " "
  ["ddd"]=>
  bool(false)
}

#長名オプションも扱いはほとんど同じ
#ただ `-aaaYYY` のように長名だと連結指定出来ない(そりゃそうだ)

総括

phpでコマンドオプションの制御をする場合は原則、長名オプションを使った方が誤作動が少ない
on/offのスイッチなら単名オプションでも可
オプションの厳密な制御が必要ならPEAR::Console_CommandLineを使うべき

onomame
C#を使うのはVisual Studioがあるから Javaを使うのはVisual Studioを使う必要が無いから PHPを使うのはコンパイル環境がなくていいから Perl/Rubyを使わないのは良さを知らないから Pythonを使うのはAWSでサーバーレスで動くから
http://materialbook.futh.net
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away