0

I'm relatively new to this field, and I'm running my shell script named "statsrandomrun.sh" with following code snippets:

#!/bin/bash
while getopts "m:s:xh" opt; do
  case $opt in
    m)
      MU=$OPTARG; mflag=true; ;;
    s)
      SIGMA=$OPTARG; sflag=true; ;;
    h)
      usage; exit;;
    x)
      xflag=true ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "HaHa! Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

but it seems though whenever I pass this command

/.statsrandomrun.sh -m 

I never see

echo "HaHa! Option -$OPTARG requires an argument." >&2

working, which I implemented in the above snippet. My bash just shows me some other message:

option requires an argument -- m

which I did not obviously put in my code. Also there follows another line

Invalid option: -

I expect this to take place, because the output from help getopts contains the following:

If a required argument is not found, getopts places a ':' into NAME and sets OPTARG to the option character found.

What is happening? Any ideas? I'd appreciate any help in advance :)

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • 1
    Here's a couple of resources.. http://wiki.bash-hackers.org/howto/getopts_tutorial and http://mywiki.wooledge.org/BashFAQ/035?highlight=%28getopts%29. Both of these sites have a lot of good information about shell scripting. – I0_ol Jul 21 '17 at 16:05
  • When I run your script: `script.sh -m` I get `script.sh: option requires an argument -- m` and then one line below `Invalid option: -` – I0_ol Jul 21 '17 at 16:11
  • What's the "shebang" line in your script? – glenn jackman Jul 21 '17 at 17:00
  • @gleen I just found out that when I use `#!/bin/sh` I get the msg `No arg for -m option` whereas when I use `#!/bin/bash` I receive `option requires an argument --m` message. So I edited the post. But with `#!/bin/bash` I still don't get the echo msg I want. – Jangwhan Jeong Jul 21 '17 at 20:35
  • If you want more control than getopts provides (including control over error messages), do the parsing yourself. See [BashFAQ #35](http://mywiki.wooledge.org/BashFAQ/035) – Charles Duffy Jul 21 '17 at 20:41
  • @I0_ol After I changed my shebang to `#!/bin/bash`, I see these messages too but that isn't the thing I wanted bash to show me. I wanted my echo `"haha ! option -m requires an argument"`, not `option requires an argument -- m`. The latter one is built-in msg, I guess. – Jangwhan Jeong Jul 21 '17 at 20:42
  • @CharlesDuffy Actually it's based on this source [http://wiki.bash-hackers.org/howto/getopts_tutorial](http://wiki.bash-hackers.org/howto/getopts_tutorial). It says `:` would activate in such case as mine. – Jangwhan Jeong Jul 21 '17 at 20:48
  • @CharlesDuffy I notice you erased your comment just now. I'll try to look up to your source [BashFAQ #35](http://mywiki.wooledge.org/BashFAQ/035). Maybe I need some customization to get things work, like you said. Thanks. – Jangwhan Jeong Jul 21 '17 at 20:52
  • btw, the docs say that `$OPTARG`, not `$name` (which is in your case `$opt`), will be set to `:` in the relevant case. – Charles Duffy Jul 21 '17 at 20:59
  • 1
    @CharlesDuffy Nop, the docs say `$name` is set to `:` and `$OPTARG` is set to the option character, but only in **silence mode** . In **non silence mode**, `?` is instead placed in `$name` and `$OPTARG` is unset, and a diagnostic messsage is printed. That explains everything! I was forcing **silence mode** option to work in **non silence mode**. Also this explains why I see this seemingly unnecessary line `Invalid option -`. Case solved... Thxs everyone. – Jangwhan Jeong Jul 21 '17 at 21:17
  • Feel free to write up the above as an answer -- that way you can accept it to mark your problem solved, and if it's helpful to other folks they can upvote it. – Charles Duffy Jul 21 '17 at 21:18

1 Answers1

2

According to the documentation, which is help getopts,

getopts: getopts optstring name [arg]

OPTSTRING contains the option letters to be recognized; if a letter is followed by a colon, the option is expected to have an argument, which should be separated from it by white space.

getopts reports errors in one of two ways. If the first character of OPTSTRING is a colon, getopts uses silent error reporting. In this mode, no error messages are printed. ................ If a required argument is not found, getopts places a ':' into NAME and sets OPTARG to the option character found. If getopts is not in silent mode, ........... If a required argument is not found, a '?' is placed in NAME, OPTARG is unset, and a diagnostic message is printed.

As I implemented my getopts function in non-silence mode, this missing argument after /.statsrandomrun.sh -m triggered ? to be stored in $Name (in my case $opt) with no content in $OPTARG.

So these lines of code were executed:

  \?)
  echo "Invalid option: -$OPTARG" >&2
  exit 1
  ;;

which produced Invalid option: - together with built-in diagnostic msg.

Instead to get the result I wanted I should have used silence mode as in

#!/bin/bash
while getopts ":m:s:xh" opt; do
#codes
done

by adding a preceding colon in OPTSTRING.