Bharat Sinha
Bharat Sinha

Reputation: 14363

Shell Script : how to make getopts just read the first character post `-`

I have a shell script testShell.sh which uses getopts as below:

#!/bin/bash
while getopts ":j:e:" option; do
    case "$option" in
        j) MYHOSTNAME=$OPTARG ;;
        e) SCRIPT_PATH=$OPTARG ;;
        *) ;;
    esac
done

echo "j=$MYHOSTNAME"
echo "e=$SCRIPT_PATH"
shift $((OPTIND - 1))
echo "remaining=$@"

When I test run it like following:

$ testShell.sh  -jvalue1 -evalue4 -Djvalue3  -pvalue2

The output which I get is following:

j=value3
e=2
remaining=

But I would like the output as:

j=value1
e=value4
remaining=-Djvalue3 -pvalue2

Is it possible to make sure that getopts only looks at first character post - symbol? so that it doesn't interpret -Djvalue3 as -jvalue3 and -pvalue2 as -e2.

Upvotes: 1

Views: 404

Answers (3)

Bharat Sinha
Bharat Sinha

Reputation: 14363

After posting it on 3 forums and searching everywhere... eventually I tried the following and it worked...

testShell.sh  -jvalue1 -evalue4 -- -Djvalue3  -pvalue2

Notice

--  

after -evalue4

And the output was

j=value1
e=value4
remaining=-Djvalue3 -pvalue2

I believe -- asks getopts to stop processing options.

EDIT: Here is the link which explains how this work.

Upvotes: 1

glenn jackman
glenn jackman

Reputation: 246807

You could do your option processing manually:

set -- -jvalue1 -evalue4 -Djvalue3 -pvalue2

remaining=()
for arg; do
    case $arg in
        -j*) j=${arg#-j} ;;
        -e*) e=${arg#-e} ;;
        *)   remaining+=($arg) ;;
    esac
done
printf "%s='%s'\n" j "$j" e "$e" remaining "${remaining[*]}"

which outputs

j='value1'
e='value4'
remaining='-Djvalue3 -pvalue2'

This way you don't have to rely on the user inputting the arguments in a particular way, such as adding -- in the middle, or forcing -j and -e to come first.

Upvotes: 1

aayoubi
aayoubi

Reputation: 12069

You can add a break after j):

#!/bin/bash
while getopts ":j:e:" option; do
    case "$option" in
        j) MYHOSTNAME=$OPTARG ; break ;;
        e) SCRIPT_PATH=$OPTARG ;;
        *) ;;
    esac
done

echo "j=$MYHOSTNAME"
echo "e=$SCRIPT_PATH"
shift $((OPTIND - 1))
echo "remaining=$@"

Output:

$ bash test.sh -jvalue1 -Djvalue3 -pvalue2
j=value1
e=
remaining=-Djvalue3 -pvalue2

Output with spaces between option / arguments:

$ bash test.sh  -jvalue1 -evalue4 -D jvalue3  -p value2
j=value1
e=value4
remaining=jvalue3 -p value2

Upvotes: 1

Related Questions