How can I pass optional parameters to another comm

2019-05-01 17:44发布

问题:

I am writing a bash script that takes in some optional parameters. I want to translate them and pass them to another script. However, I'm having a hard time passing the optional parameters gracefully.

Here's a outline of what I managed to get working in pseudocode:

a.sh:

if arg1 in arguments; then
    firstArg="first argument"
fi
if arg2 in arguments; then
    secondArg="second argument"
fi

./b.sh $firstArg $secondArg "default argument"

Note the spaces in the arguments.

b.sh:

for arg in "$@"
do
    echo $arg
done

I want to call b.sh, optionally with firstArg and secondArg and a default argument like so:

./b.sh $firstArg $secondArg "default argument"

The problem with this is that if $firstArg or $secondArg are strings with spaces, they will be represented as multiple arguments, and the output will be something like:

first
argument
second
argument
default argument

Okay, that's easy to fix, let's capture the entire string of the arguments by adding quotes around it like so:

./b.sh "$firstArg" "$secondArg" "defaultArg"

Problem is if, for example, firstArg is not set, it results in a blank line (as it will interpret "" as a parameter), so the output will be something like:

(blank line here)
second argument
defaultArg

I've also tried constructing a string and passing it to the shell script, but it doesn't seem to work that way either (it interprets the whole string as an argument, even if I add separate the arguments with quotes).

Note that calling b.sh from my command line with the arguments quoted works fine. Is there a way to mimic how this works from within a bash script?

回答1:

If you literally want to copy all arguments given, but add one more:

# this works in any POSIX shell
./b.sh "$@" defaultArg

Alternately, to explicitly pass firstArg and secondArg, but only if they exist (note that set-to-an-empty-value counts as "existing" here):

# this works in any POSIX shell
./b.sh ${firstArg+"$firstArg"} ${secondArg+"$secondArg"} defaultArg

If you want to treat set-to-an-empty-value as not existing:

# this works in any POSIX shell
./b.sh ${firstArg:+"$firstArg"} ${secondArg:+"$secondArg"} defaultArg

An alternate approach is to build up an array of arguments:

# this requires bash or another shell with arrays and append syntax
# be sure any script using this starts with #!/bin/bash
b_args=( )
[[ $firstArg ]] && b_args+=( "$firstArg" )
[[ $secondArg ]] && b_args+=( "$secondArg" )
b_args+=( "default argument" )
./b.sh "${b_args[@]}"

If you want something with the same flexibility as the array method, but without the compatibility issues, define a function; within it, you can safely override "$@" without impacting the rest of the script:

runB() {
  set --
  [ -n "$firstArg" ]  && set -- "$@" "$firstArg"
  [ -n "$secondArg" ] && set -- "$@" "$secondArg"
  ./b.sh "$@" "default argument"
}


回答2:

Use an array:

args=()

if [ ... ]; then
    args+=( "first argument" )
fi

if [ ... ]; then
    args+=( "second argument" )
fi

./b.sh "${args[@]}" "default argument"


标签: bash shell