Bash:使用多个可选标志调用脚本 - 它总是选择第一个并忽略其他

问题描述

我有一个 bash 方法

  SUITE=''
  FILTER=''
  COVERAGE=''
  COVERAGE_REPORT_PATH="tests/Report"

  while getopts :s:f:c: flag # do not remove first colon as it makes flags optional
  do
      case "${flag}" in
          s) SUITE="--testsuite=${OPTARG}";;
          f) FILTER="--filter=${OPTARG}";;
          c) COVERAGE="--coverage-html ${COVERAGE_REPORT_PATH}";;
      esac
  done

  echo "docker exec -it my_api_1 ./vendor/bin/PHPunit ${SUITE} ${FILTER} ${COVERAGE}";

当我运行它时:./local.sh PHPunit -s Unit 它打印:

docker exec -it my_api_1 ./vendor/bin/PHPunit --testsuite=Unit

当我运行它时:./local.sh PHPunit -f MyClass 它打印:

docker exec -it my_api_1 ./vendor/bin/PHPunit --filter=MyClass

但是当我使用两个标志运行它时:./local.sh PHPunit -s Unit -f MyClass 它只打印第一个

docker exec -it my_api_1 ./vendor/bin/PHPunit --testsuite=Unit

我做错了什么?

解决方法

这是我在 Mac 上看到的:

IRV-JISHAK-OSX:tmp jishak$ ./local.sh 
docker exec -it my_api_1 ./vendor/bin/phpunit   
IRV-JISHAK-OSX:tmp jishak$ ./local.sh phpunit -s Unit
docker exec -it my_api_1 ./vendor/bin/phpunit   
IRV-JISHAK-OSX:tmp jishak$ ./local.sh phpunit -s Unit
docker exec -it my_api_1 ./vendor/bin/phpunit   
IRV-JISHAK-OSX:tmp jishak$ ./local.sh -s Unit phpunit
docker exec -it my_api_1 ./vendor/bin/phpunit --testsuite=Unit  
IRV-JISHAK-OSX:tmp jishak$  ./local.sh phpunit -f MyClass
docker exec -it my_api_1 ./vendor/bin/phpunit   
IRV-JISHAK-OSX:tmp jishak$  ./local.sh -f MyClass
docker exec -it my_api_1 ./vendor/bin/phpunit  --filter=MyClass 
IRV-JISHAK-OSX:tmp jishak$ ./local.sh phpunit -s Unit -f MyClass
docker exec -it my_api_1 ./vendor/bin/phpunit   
IRV-JISHAK-OSX:tmp jishak$ ./local.sh -s Unit -f MyClass
docker exec -it my_api_1 ./vendor/bin/phpunit --testsuite=Unit --filter=MyClass 

正如@markp-fuso 在上面指出的那样,使用 phpunit 参数会破坏解析,因为它被视为未处理的选项。我认为你可以将它移到最后或完全放弃它以使其工作。

,

对于像这样的简单选项,我真的看不到 getopts 的用途。相反,你可以做的是

#!/usr/bin/env bash
SUITE=''
FILTER=''
COVERAGE=''
COVERAGE_REPORT_PATH="tests/Report"

while(($# > 0)); do
    case ${1} in
        -s) shift; SUITE="--testsuite=${1}";;
        -f) shift; FILTER="--filter=${1}";;
        -c) COVERAGE="--coverage-html ${COVERAGE_REPORT_PATH}";;
    esac
    shift
done

echo "docker exec -it my_api_1 ./vendor/bin/phpunit ${SUITE} ${FILTER} ${COVERAGE}";

并在 shift 循环中使用内置的 while 循环遍历参数,直到没有剩余。

./parseopts phpunit -s Unit -f MyClass

输出

docker exec -it my_api_1 ./vendor/bin/phpunit --testsuite=Unit --filter=MyClass