Shell 可选地向脚本中的命令传递参数

Shell 可选地向脚本中的命令传递参数,shell,sh,Shell,Sh,我有一个shell脚本,其中有这样一个部分: if [ "$condition" -eq 1 ]; then external_command -argument value1 else external_command -argument value1 -second_argument value2 fi 我被这种重复所困扰,所以我尝试了这个: arg="-second_argument" val="value2" if [ "$condition" -eq 1 ]; the

我有一个shell脚本,其中有这样一个部分:

if [ "$condition" -eq 1 ]; then
    external_command -argument value1
else
    external_command -argument value1 -second_argument value2
fi
我被这种重复所困扰,所以我尝试了这个:

arg="-second_argument"
val="value2"
if [ "$condition" -eq 1 ]; then
    arg=""
    val=""
fi
external_command -argument value1 "$arg" "$val"
它不起作用,因为
external_命令
仍然将空字符串作为不同的参数获取并发出抱怨

有没有一种方法可以在不重复构建命令行的情况下做到这一点?在我的实际代码中有4种不同的条件,因此有很多不必要的重复

如果我使用的是Bash,我会遵循并为命令参数构建一个数组,但我不是。

试试看

second=
if [ "$condition" -ne 1 ]; then
    second="-second_argument value2"
fi
external_command -argument value1 $second
请注意双引号/没有双引号。
尽管user1934428是正确的,但如果-second_参数的值中有空格,则可能会出现问题。

标准的解决方法是使用位置参数代替数组。假设您不关心当前值:

shift $#  # Clear them; optional, as the next line overwrites whatever was there
set -- -argument value1
if [ "$condition" -eq 1 ]; then
  set -- "$@" "-second_argument"  "value2"
fi
external_command "$@"
如果您确实关心当前值,请在子shell中运行该块:

(
  set -- -argument value1
  if [ "$condition" -eq 1 ]; then
    set -- "$@" "-second_argument"  "value2"
  fi
  external_command "$@"
)

或者,定义一个函数,该函数已经有自己的位置参数集

run_external () {
  condition=$1
  set -- -argument value1
  if [ "$condition" -eq 1 ]; then
    set -- "$@" -second_argument value2
  fi
  external_command "$@"
}

run_external "$condition"

如果在应给出第二个条件时填充变量,否则将其置为未设置状态,则有另一个符合POSIX的选项:

# have a variable set ONLY IF you want the extra arguments passed
if [ "$condition" -eq 1 ]; then
  unset want_extra_args
else
  want_extra_args=1
fi

# and put those arguments in a ${var+val} expansion
external_command -argument value1 ${want_extra_args+-second_argument value2}
您可以使用引号和其他展开式,也就是说,以下内容是有效的:

external_command ... ${want_extra_args+-second_argument "$value2"}

如果您确定
val
不包含空格,您可以简单地省去引号,但一般来说,我认为这不能在纯Posix shell中完成,而不使用
eval
返回到肮脏的技巧。我绝对不想看eval!听起来我一直在重复我自己。或者制作一个Bash脚本!明智的选择。另一种可能是切换到Zsh,在这里您可以不使用bash中必需的数组技巧。我个人更喜欢Zsh而不是bash,但我知道也有很多人支持bash。如果可以选择切换shell,那么使用
bash
Zsh
并不重要,因为两者都有数组。是的,不幸的是,存在空格!不仅仅是空格,还有可能导致分词的任何内容(基于
IFS
的值)或任何可以扩展为模式的内容。请参阅,以获取有关此操作通常有错误的原因的详细解释以及各种替代方法。因此,当我将
$@
作为参数传递给命令时,它实际上被看作是个人的争论?是的;这就是
$@
$*
之间的区别。引用时,
“$@”
扩展为0个或多个不同的字,每个位置参数一个,
“$*”
扩展为正好一个字(可能为空);它的扩展产生0个或更多被传递的参数。显然不是!他们中的很多人是;幸运的是你不需要这个。