(可选)将参数传递给脚本中的命令

Optionally passing arguments to commands in a script

提问人:miken32 提问时间:4/12/2018 更新时间:4/14/2018 访问量:113

问:

我有一个 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"

它没有用,因为 still 将空字符串作为不同的参数和抱怨。external_command

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

如果我使用的是 Bash,我会按照 Bash FAQ 050 为命令参数构建一个数组,但我不是。

壳牌 SH

评论

1赞 user1934428 4/12/2018
如果您确定它不包含空格,您可以简单地省略引号,但总的来说,我认为这不能在 Pure Posix shell 中完成,而不会使用 .valeval
0赞 miken32 4/13/2018
我绝对不想看 eval!听起来我被困在重复自己身上。或者制作一个 Bash 脚本!
0赞 user1934428 4/13/2018
一个明智的选择。另一种可能性是切换到 Zsh,在那里你可以在没有 bash 中必要的数组技巧的情况下做到这一点。我个人更喜欢 Zsh 而不是 bash,但我知道也有很多支持 bash 的论据。
0赞 chepner 4/14/2018
如果可以选择切换 shell,那么是否使用 或 并不重要,因为两者都有数组。bashzsh

答:

-1赞 torbatamas 4/12/2018 #1

试试吧

second=
if [ "$condition" -ne 1 ]; then
    second="-second_argument value2"
fi
external_command -argument value1 $second

请注意双引号/没有双引号。 尽管 user1934428 是正确的,但如果空格值为 -second_argument,则可能会出现问题。

评论

0赞 miken32 4/13/2018
是的,不幸的是有空格!
0赞 chepner 4/14/2018
不仅仅是空格,而是任何有助于拆分单词的东西(基于 的值)或任何可以扩展为模式的东西。IFS
1赞 Charles Duffy 4/14/2018
请参阅 BashFAQ #50 来详细解释为什么这种做法通常是错误的,以及各种替代方案。
2赞 chepner 4/14/2018 #2

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

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"

评论

0赞 miken32 4/14/2018
因此,当我将参数传递给命令时,它实际上被视为单个参数?$@
2赞 chepner 4/14/2018
是的;这就是 和 之间的区别。引用时,扩展为 0 个或多个不同的单词,每个位置参数一个,同时扩展到一个(可能是空的)单词。$@$*"$@""$*"
2赞 chepner 4/14/2018
需要明确的是,它本身不是作为参数传递的;它的扩展产生 0 个或多个传递的参数。$@
1赞 Charles Duffy 4/14/2018 #3

如果在给定第二个条件时填充变量,否则将其保留为未设置状态,则还有另一个符合 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"}

评论

0赞 miken32 4/26/2018
很好,我认为很多更深奥的扩展都是特定于 Bash 的。显然不是!
0赞 Charles Duffy 4/26/2018
他们中的很多人是;只是很幸运,你需要的这个特定的不是。