Search code examples
linuxkshstring-parsinggetopt

Parsing long and short args in ksh using loop


I am trying to parse arguments in ksh. Can't do getopt for the same as in short options I have two/three characters. Currently I am using for loop. Its stupid but am unable to find something better.

Question: How do I set option+value as one unit in order to parse? Also if eval set -- $option will help me then how do I use it? echo on option does not show the expected "--" at the end. Am I assuming something wrong?

I am thinking of using a variable to keep track of when an option is found but this method seems too confusing and unnecessary.

Thanks for your time and help.

Update 1: Adding code as pointed out. Thanks to markp, Andre Gelinas and random down-voter in making this question better. Trying to execute the script as given in line 2 and 3 of code - or any other combination of short and long options passed together.

#!/bin/ksh
# bash script1.sh --one 123 --two 234 --three "some string"
# bash script1.sh -o 123 -t 234 -th "some string"

# the following creates problems for short options. 
#options=$(getopt -o o:t:th: -l one:two:three: "--" "$@")

#Since the below `eval set -- "$options"` did not append "--" at the end
#eval set -- "$options"

for i in $@; do
    options="$options $i"
done
options="$options --"

# TODO capture args into variables

Attempted code below TODO until now:

for i in $options; do
    echo $i
done

Will be capturing the args using:

while true; do
    case $1 in
        --one|-o) shift; ONE=$1
        ;;
        --two|-t) shift; TWO=$1
        ;;
        --three|-th) shift; THREE=$1
        ;;
        --) shift; break
        ;;
    esac
done

Solution

  • Try something like this :

    #!/bin/ksh
    
    #Default value
    ONE=123
    TWO=456
    
    
    # getopts configuration
    USAGE="[-author?Andre Gelinas <andre.gelinas@foo.bar>]"
    USAGE+="[-copyright?2018]"
    USAGE+="[+NAME?TestGetOpts.sh]"
    USAGE+="[+DESCRIPTION?Try out for GetOps]"
    USAGE+="[o:one]#[one:=$ONE?First.]"
    USAGE+="[s:second]#[second:=$TWO?Second.]"
    USAGE+="[t:three]:[three?Third.]"
    USAGE+=$'[+SEE ALSO?\aman\a(1), \aGetOpts\a(1)]'
    
    while getopts "$USAGE" optchar ; do
        case $optchar in
                    o)  ONE=$OPTARG ;;
                    s)  TWO=$OPTARG ;;
                    t)  THREE=$OPTARG ;;
        esac
    done
    
    print "ONE = "$ONE
    print "TWO = "$TWO
    print "THREE = "$THREE
    

    You can use either --one or -o. Using --man or --help are also working. Also -o and -s are numeric only, but -t will take anything. Hope this help.