2

I'm supporting below arguments to the script. I want to find out duplicate arguments when its passed and throw an error. Can you please help me.

#! /bin/sh
VCFile=
gCFFile=
PW=xyzzy

while test $# -gt 0 
do
  option=$(echo $1 | tr a-z A-Z)
  case $option in

(-VO)    shift
          VCfile=$1
          ;;
(-CON)  shift
          gCFFile=$1
          ;;
(-PASSWORD) shift
          PW=$1
          ;;
(*)     
          print "\nerror -The command line argument $1 is invalid\n"
          print "Testscript has aborted.\n"
          exit 2  
          ;;
   esac
   shift
done

./Install.sh -VO abc.txt -CON tt.txt - pass
./Install.sh -VO abc.txt -CON tt.txt -ss

error -The command line argument -ss is invalid
Testscript has aborted.

if running with dup parameters like below

./Install.sh -VO abc.txt -CON tt.txt -CON ta.txt -PASSWORD ABC -PASSWORD non 

--doesn't fail , Here I want to throw an error as duplicate options are entered.

ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
user2347191
  • 99
  • 1
  • 2
  • 14
  • what is error you are getting ? and what you not want? – Shravan Yadav Jun 30 '16 at 02:37
  • I want to throw an error. now the program is like below. I'm not sure how to find duplicate arguments in shell. while [[ $# > 2 ]] do key="$2" case $key in -gm|--gitremote) GITREMOTE="$3" shift ;; -ig|--installgrunt) echo 'test' shift ;; *) # unknown option ;; esac shift done – user2347191 Jun 30 '16 at 02:40
  • please provide live example instead of mentioning "duplicate entries entered here" – Shravan Yadav Jun 30 '16 at 02:41
  • 1
    Modified the content. can u please help me. thanks in advance – user2347191 Jun 30 '16 at 02:53
  • Set all three variables to empty (don't default the password). When an option is recognized, check that the corresponding variable is empty — complaining if it isn't. Arguably, you should be testing that there is a `$1` after you shift the option out of the way. You'll have to decide whether `./Install.sh -VO '' -VO abc.txt` counts as a duplicate entry or not. The first argument is an empty string. If you just check the variable `$VCfile`, you won't know that it was already set (to an empty string). If it matters, track whether the option was seen before separately from the value. – Jonathan Leffler Jun 30 '16 at 04:27

2 Answers2

4

Just check if the value has already been set.

#!/bin/sh
unset VCFile
unset gCFFile
unset PW  # set default below

die() { echo "$@"; exit 1; } >&2
while test $# -gt 0 
do
  option=$(echo $1 | tr a-z A-Z)
  case $option in

(-VO)    shift
          test "${VCFile+set}" = set && die -VO set twice
          VCfile=$1
          ;;
(-CON)  shift
          test "${gCFFile+set}" = set && die -CON given twice
          gCFFile=$1
          ;;
(-PASSWORD) shift
          test "${PW+set}" = set && die -PASSWORD given twice
          PW=$1
          ;;
(*)     
          die "error -The command line argument $1 is invalid
          ;;
   esac
   shift
done
: ${PW=xyzzy}  # if -PASSWORD was not given, set a default
William Pursell
  • 204,365
  • 48
  • 270
  • 300
2

You can use below code before while loop.

if [ `echo "$@" | grep -o "\-CON" | wc -l` -gt 0 ] || [ `echo "$@" | grep -o "\-PASSWORD" | wc -l` -gt 0 ] ||  [ `echo "$@" | grep -o "\-VO" | wc -l` -gt 0 ]
then
echo "  Duplicate set of parameter is passed. $# is invalid\n"
echo "Testscript has aborted.\n"
exit 0
fi

OR you can add in case statement to get which parameter is duplicate.

while  test $# -gt 0
do
  option=$(echo $1 | tr a-z A-Z)
  case $option in

(-VO)    shift
          VCfile=$1
          if  [ `echo "$@" | grep -o "\-VO" | wc -l` -gt 0 ]
          then
             echo "Duplicate set of parameter is passed for -VO . Parameters passed are invalid\n"
             echo "Testscript has aborted.\n"
          exit 0
          fi
          ;;
(-CON)  shift
          gCFFile=$1;
          if  [ `echo "$@" | grep -o "\-CON" | wc -l` -gt 0 ]
          then
             echo "Duplicate set of parameter is passed for -CON . Parameters passed are invalid\n"
             echo "Testscript has aborted.\n"
          exit 0
          fi
          ;;
(-PASSWORD) shift
          PW=$1
          if  [ `echo "$@" | grep -o "\-PASSWORD" | wc -l` -gt 0 ]
          then
             echo "Duplicate set of parameter is passed for -PASSWORD . Parameters passed are invalid\n"
             echo "Testscript has aborted.\n"
          exit 0
          fi
          ;;
(*)
          echo "\nerror -The command line argument $1 is invalid\n"
          echo "Testscript has aborted.\n"
          exit 2
          ;;
   esac
   shift
done

let me know if it is working.

Shravan Yadav
  • 1,297
  • 1
  • 14
  • 26
  • The use of backticks instead of `$(…)` is usually not a good choice. The use of `echo $@` is a bit dubious; you should use `echo "$@"`, probably. You could use the `-c` option to `grep` to count, instead of `wc`. Your code would reject `./Install.sh -VO MY-PASSWORD.TXT -PASSWORD MY-VO.BAT` because both `-VO` and `-PASSWORD` appear twice in the text. – Jonathan Leffler Jun 30 '16 at 04:30
  • have you tried the grep -o -c "\-CON"? please try as it is not working. Edited the code to use "$@". Please elaborate how $(..) is better that backticks ``? – Shravan Yadav Jun 30 '16 at 05:03
  • For backticks, see [What is the benefit of using `$(…)` instead of backticks in shell scripts?](https://stackoverflow.com/questions/9449778/) – Jonathan Leffler Jun 30 '16 at 05:06
  • thanks for the backticks link. You mentioned to use grep -c to count. So how to use grep -c in this case? – Shravan Yadav Jun 30 '16 at 05:12
  • Testing on Mac OS X 10.11.5, I get `1` from `(set -- Eligible -CON nostradumus-CONCEPT; echo "$@" | grep -c -o "\-CON" )` whereas I get `2` from `(set -- Eligible -CON nostradumus-CONCEPT; echo "$@" | grep -o "\-CON" | wc -l)`. That's not what I expected. I guess the key is in the wording of the man page: _`-c` Only a count of selected lines is written to standard output._ Even when there are several entries found on a single line, it is still a single line so `-c` only counts `1`, not `2`. I'm not sure that's helpful, but it seems to be the actual behaviour. So, you can't use the `-c` option. – Jonathan Leffler Jun 30 '16 at 05:14