调用 shift 1 后 unshift args

Ale*_*lls 8 shell bash arguments

我有这个场景

first_arg="$1";

if foo; then
    shift 1;
    node foo.js "$@"

elif bar; then

   shift 1;
    node bar.js "$@"

elif baz; then

   shift 1;
   node baz.js "$@"

else

   node default.js "$@"

fi
Run Code Online (Sandbox Code Playgroud)

我想把上面的变成这样:

first_arg="$1";
shift 1;

if foo; then

    node foo.js "$@"

elif bar; then

    node bar.js "$@"

elif baz; then

   node baz.js "$@"

else

   unshift 1;
   node default.js "$@"

fi
Run Code Online (Sandbox Code Playgroud)

但我不确定是否有像 unshift 这样的操作符,这是我刚刚编出来的。一种解决方法可能是这样的:

node default.js "$first_arg" "$@"
Run Code Online (Sandbox Code Playgroud)

但是当我尝试这样做时,我得到了奇怪的行为。

Ini*_*ian 13

您永远不需要首先使用shift 1。只需使用位置参数并围绕它们的索引切片来传递参数。

first_arg="$1"
Run Code Online (Sandbox Code Playgroud)

完成此操作后,其余参数可以作为"${@:2}". 该符号是一种表示从位置参数 2 到列表末尾的方法。

为您的示例使用构造将是

node foo.js "${@:2}"
Run Code Online (Sandbox Code Playgroud)

最后else一部分做

node default.js "$1" "${@:2}"
Run Code Online (Sandbox Code Playgroud)

这与"$@"没有完成位置参数移位相同。

  • `"$@"` 比 `"$1" "${@:2}"` 更好,如果 `$@` 为空,它将创建一个额外的参数。 (6认同)

jes*_*e_b 9

您可以将参数保存在数组中:

args=( "$@"  )  # use double quotes
shift 1

if foo; then
  node foo.js "$@"
elif bar; then
  node bar.js "$@"
elif baz; then
  node baz.js "$@"
else
  node default.js "${args[@]}"
fi
Run Code Online (Sandbox Code Playgroud)


Kus*_*nda 8

你尝试的事情:

first_arg=$1
shift

# ...later...

else
    node default.js "$first_arg" "$@"
fi
Run Code Online (Sandbox Code Playgroud)

如果至少有一个命令行参数,这将与您的第一个变体相同。

没有命令行参数"$first_arg"仍然是一个空字符串,因此是一个参数,而"$@"不会生成一个空字符串。

如果您的 Node 应用程序在命令行上接受一个空参数,那么这可能会使应用程序在您的两个代码变体中的行为有所不同。

如果在没有命令行参数的情况下调用您的脚本是一件有效的事情,您可以这样做

node default.js ${first_arg:+"$first_arg"} "$@"
Run Code Online (Sandbox Code Playgroud)

${first_arg:+"$first_arg"}如果first_arg为空或未设置,则where将扩展为空,但"$first_arg"如果first_arg设置为非空字符串。或者,如果要导致未设置或空变量的显式失败:

node default.js "${first_arg:?Error, no command line arguments}" "$@"
Run Code Online (Sandbox Code Playgroud)

替代方法包括制作Jesse_b 在他的回答中显示$@bash数组副本。

$first_arg$@

set -- "$first_arg" "$@"`
Run Code Online (Sandbox Code Playgroud)

不会因为这样的工作将包括一个空的说法是$1$@如果在命令行参数失踪。

set -- ${first_arg:+"$first_arg"} "$@"`
Run Code Online (Sandbox Code Playgroud)

如果$first_arg为空或变量不存在,您将不会“取消移动”任何内容。


请注意,shift 与 shift 1 相同,并且单个语句不需要以 ; 结束。除非在同一行上跟随另一个语句(换行符是命令终止符,就像;)。