【问题标题】:How can I pass optional parameters to another command within a bash script?如何将可选参数传递给 bash 脚本中的另一个命令?
【发布时间】:2015-05-06 20:09:06
【问题描述】:

我正在编写一个接受一些可选参数的 bash 脚本。我想翻译它们并将它们传递给另一个脚本。但是,我很难优雅地传递可选参数。

这是我设法用伪代码工作的概要:

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"

注意参数中的空格。

b.sh:

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

我想调用b.sh,可以选择使用firstArgsecondArg 以及像这样的默认参数:

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

这样做的问题是,如果$firstArg$secondArg 是带有空格的字符串,它们将被表示为多个参数,并且输出将类似于:

first
argument
second
argument
default argument

好的,这很容易解决,让我们通过在其周围添加引号来捕获整个参数字符串:

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

问题是,例如,firstArg 未设置,它会导致空行(因为它将"" 解释为参数),因此输出将类似于:

(blank line here)
second argument
defaultArg

我也尝试过构造一个字符串并将其传递给 shell 脚本,但它似乎也不是这样工作的(它将整个字符串解释为一个参数,即使我用引号将参数分开) .

请注意,使用引用的参数从我的命令行调用 b.sh 可以正常工作。有没有办法在 bash 脚本中模仿它的工作原理?

【问题讨论】:

  • 旁白:仅仅因为我正在复制您的线索并在可执行文件上使用 .sh 扩展名(即,具有 +x 权限的文件,execv()-family 调用将成功)不会'不是说这是个好主意。一般来说,UNIX 中的命令不应该有任何扩展名,无论它们是通过 shell 脚本、Python 脚本、编译的二进制文件等提供的。
  • 您能否明确说明这是否适用于使用#!/bin/sh#!/bin/bash 的代码?

标签: bash shell


【解决方案1】:

如果你真的想复制所有给定的参数,但再添加一个:

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

或者,显式传递firstArgsecondArg,但前提是它们存在(请注意,此处设置为空值算作“存在”):

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

如果您想将 set-to-an-empty-value 视为不存在:

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

另一种方法是建立一个参数数组:

# 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[@]}"

如果你想要与数组方法具有相同灵活性但又没有兼容性问题的东西,请定义一个函数;在其中,您可以安全地覆盖 "$@" 而不会影响脚本的其余部分:

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

【讨论】:

  • 这里引用"$@" 是不是错了?之后它就不再是分词的主题了……不是吗?
  • 好答案!发表评论时我没有正确回答问题。
  • 感谢您的回答!第二块和第三块工作正常。真的让我为这个而摸不着头脑。
  • 第四种形式对你有用吗?除非您使用的是非常旧的 bash(3.2 之前),否则这实际上有点令人惊讶。你能描述一下它是如何失败的吗?
  • 我只是没试过,我试试看好不好用。
【解决方案2】:

使用数组:

args=()

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

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

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

【讨论】:

  • @EtanReisner 不,因为在 OP 的示例中,$firstArg 可能根本没有设置(但使用了),但如果它被设置,它将被设置为字符串文字(在以上 sn-p).
  • 啊,我认为这些是实际的第一个和第二个参数的占位符,而不是文字字符串(在 OP 和这里),因为你忽略了对参数本身的实际测试,所以我没有填写这些。正如所写的那样,这没有那个问题,但正如所写的那样,这也只是解决方案的一半(而且我认为不能完全正确地解决它)。
  • 我知道你是从哪里来的。但是,将./b.sh "$firstArg" "$secondArg" "defaultArg" 作为可能的解决方案的OP(并将其唯一的错误描述为传递空参数而不是根本不提供它们)表明使用文字字符串"first argument""second argument" 在早期只是草率问题。
  • @CharlesDuffy 我明白了;我承认我当时可能没有完全得到这个问题,但话又说回来,这只是ifs 的构造问题,因为您也建议将此作为解决方案。除非我仍然缺少一些东西:-)
猜你喜欢
  • 1970-01-01
  • 2022-12-08
  • 1970-01-01
  • 1970-01-01
  • 2018-12-10
  • 1970-01-01
  • 2018-07-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多