0

I have a bash method:

  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}";

When I run it with: ./local.sh phpunit -s Unit it prints:

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

When I run it with: ./local.sh phpunit -f MyClass it prints:

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

But when I run it with both flags: ./local.sh phpunit -s Unit -f MyClass it only prints the first one:

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

What am I doing wrong?

Cyrus
  • 84,225
  • 14
  • 89
  • 153
Matt Komarnicki
  • 5,198
  • 7
  • 40
  • 92
  • 1
    `do not remove first colon as it makes flags optional` it doesn't, you just lack error handling. I can't reproduce your results - parsing stops at first argument `phpunit` and the `-s` nor `-f` are not parsed at all. This is expected - `getopt` parses arguments _in order_. Is there a `shift` missing in the source you posted? – KamilCuk Mar 10 '21 at 17:24
  • unable to reproduce your sample outputs; I **do** get the same output as Cyrus ... none of the flags are processed because the first arg (`phpunit`) is not being processed (and `shift`ed) and hence the flags are never processed; if I remove `phpunit` from the invocation then the script functions as expected (with 1, 2 or 3 flags) – markp-fuso Mar 10 '21 at 18:20
  • @KamilCuk: I believe `getopt` and `getopts` are two different bash commands. Did you mean to use `getopts` which is what the asker is using? – Joseph Ishak Mar 10 '21 at 18:44
  • @JosephIshak Yes, that's a typo, most probably because I use `getopt` in my scripts :) As for "bash commands" - `getopts` is shell internal special command, `getopt` is a normal external program from `util-linux`. – KamilCuk Mar 10 '21 at 20:00

2 Answers2

1

This is what I see on my 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 

As @markp-fuso points out above, having the phpunit argument breaks the parsing as it is being treated as an unhandled option. I think you can move it to the end or drop it altogether to get it to work.

Joseph Ishak
  • 1,194
  • 1
  • 9
  • 18
0

For simple options like this, I wouldn't really see a use for getopts. Instead what you can do is

#!/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}";

And use the shift builtin inside a while loop to cycle through the arguments until there are none left.

./parseopts phpunit -s Unit -f MyClass

Outputs

docker exec -it my_api_1 ./vendor/bin/phpunit --testsuite=Unit --filter=MyClass
644
  • 629
  • 4
  • 14