Shell script with options and argument - Update

Based on solutions below, I came up with this to accept either -q or -a as option, both with argument:

> #!/bin/bash
> 
> input_file="${1:-/dev/stdin}"
> 
> while getopts ":qa:" opt; do   case $opt in
> 
>     q)
>       string="$OPTARG"
>       echo "org = $string"
>       grep -v '^>' "$input_file" | grep -x '.\{15,30\}' | sort | uniq -c | awk '{print $2, $1}' | perl -lane ' print ">dme" . $n++ . "_count=$F[1]\n$F[0]" if ($F[1] > 2) '      
>       ;;
> 
>     a)
>       string="$OPTARG"
>       echo "org = $string"
>       grep -v '^>' "$input_file" | grep -x '.\{15,30\}' | sort | uniq -c | awk '{print $2, $1}' | perl -lane ' print ">dme" . $n++ . "_count=$F[1]\n$F[0]" if ($F[1] > 2) '  
>       ;;
> 
>     \?)
>       echo "Invalid option: -$OPTARG" >&2
>       exit 1
>       ;;
>     :)
>       echo "Option -$OPTARG requires an argument." >&2
>       exit 1
>       ;;   esac done

./script.sh -q "hsa" < test.txt > trial.txt

As advised, I took out option -m. Currently, I have the same instructions for options q and m, just for testing purposes. Option a works and yields the desired result. Option q does not throw an error but won't yield same result.

Also, I'd like to have the argument provided from the command line passed to the perl instructions, i.e. I'd like dme to be replaced with whatever is provided from the command line. Is there a way to do this? As it is now, the perl line runs fine.

Thanks!


ANSWERS:


Try to use bash, that is change

#!/bin/sh

to

#!/bin/bash

Added after the first comment:

#!/bin/bash

input_file="${1:-/dev/stdin}"

#a and q do not have arguments and are interchangeable, option m accepts a three letter string
while getopts ":qam:" opt; do
  case $opt in
    q)
      echo "-q was triggered" #, Parameter: $OPTARG" >&2
      #awk "$input_file" '{print $2, $1}' | perl -lane ' print ">one" . $n++ . "_count=$F[1]\n$F[0]" if ($F[1] > 2) ' > output1.txt
      ;;
    a)
      #perl -lane ' print ">one" . $n++ . "_count=$F[1]\n$F[0]" if ($F[1] > 2) ' < "$input_file" > output1.txt  
      echo "-a was triggered"
      ;;
    m)
      echo "-m was triggered, Parameter: $OPTARG" >&2
      string="$OPTARG"
      if [ ${#string} = 3 ]; then 
        echo "string $string has length 3! good"
      else 
        echo "string $string should be of length 3!"
      exit
      fi
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

Check that I did not forget anything from your original code. As far as i know you cannot call the the script with > between your options, but you can do this:

./script.sh -a -q -m "one" -X < test.html 
-a was triggered
-q was triggered
-m was triggered, Parameter: one
string one has length 3! good
Invalid option: -X

Notice that X is an invalid option.

Edit after Andy G updated his question: You need to change getopts like this. Check on the docs if you want : or :: after q and a.

while getopts ":q:a:" opt; do   

About the perl question: can you try this?

perl -lane ' print > "$string" . $n++ . "_count=$F[1]\n$F[0]" if ($F[1] > 2) ' 


 MORE:


 ? Running C Executable With Arguments As C Executable From Shell Script
 ? UNIX Shell scripting/Menu
 ? Find and replace: \'
 ? Find and replace: \'
 ? Find and replace: \'
 ? replace with sed on Mac OS X Leopard doesn't do what expected
 ? Change find and replace every iteration
 ? Using sed to replace text with spaces with a defined variable with slashs
 ? Grep - find and replace
 ? sed command - find and replace while excluding specific pattern in find