问题理解 bash 脚本中的参数扩展

Issue understanding a parameter expansion in a bash script

我想了解参数扩展在 bash 脚本中的作用。

third_party_bash_script

#!/bin/sh
files="${*:--}"
# For my understanding I tried to print the contents of files
echo $files 

pkill bb_stream
if [ "x$VERBOSE" != "" ]; then
        ARGS=-v1
fi
while [ 1 ]; do cat $files; done | bb_stream $ARGS

当我 运行 ./third_party_bash_script 时,它只打印一个连字符 -,没有别的。由于对我来说没有意义,我也尝试在终端中进行实验

$ set one="1" two="2" three="3"
$ files="${*:--}"
$ echo $files
one="1" two="2" three="3"
$ set four="4"
$ files="${*:--}"
four="4"

我似乎无法理解它在做什么。有人可以帮我解释 sh${*:--} 的解释吗?

"$@" 是传递给脚本的参数的 array"$*"string所有这些参数都在中间用空格连接。

"${*:--}" 是参数字符串(如果提供)(:-),否则 - 表示“从标准输入获取输入”。

"${@:--}" 是参数数组(如果提供的话)(:-),或者 - 否则表示“从标准输入获取输入”。

$ cat file
foo
bar

$ cat tst.sh
#!/usr/bin/env bash

awk '{ print FILENAME, [=11=] }' "${@:--}"

当向脚本提供 arg 时,"$@" 包含 "file",因此这是调用 awk 的 arg:

$ ./tst.sh file
file foo
file bar

当没有向脚本提供 arg 时,"$@" 为空,因此使用 - 调用 awk(意味着从标准输入读取),因为它是 arg:

$ cat file | ./tst.sh
- foo
- bar

在这种情况下,您几乎总是想使用 "${@:--}" 而不是 "${*:--}",有关 "$@""$*" 的更多信息,请参阅 https://unix.stackexchange.com/questions/41571/what-is-the-difference-between-and

${param:-default} 如果设置了 $param 且不为空,则扩展为 $param 的值,否则扩展为 default.

$* 是脚本的所有命令行参数。

${*:--}中,param*default-。如果 $* 不是空字符串,它会扩展为脚本参数。如果为空,则扩展为默认值 -.

这可以在脚本中用于实现程序从其参数中列出的文件中读取的常见行为,如果没有给出文件名参数,则从标准输入中读取。许多命令将输入​​文件名参数 - 视为标准输入。

注意: 寻址 OP 的原始、预编辑 post ...

有关不同选项的简要回顾,请参阅 shell parameter expansion

虽然其他答案引用 ${*:--}(和 ${@:--})作为从标准输入读取的替代方法,但 OP 的示例脚本更简单一些......如果变量 $*(即脚本的命令行参数)为空,然后替换为文字字符串 -.

我们可以通过几个例子看出这一点:

$ third_party_bash_script
-

$ third_party_bash_script a b c
a b c

$ echo 'a b c' | third_party_bash_script
-

如果我们用${*:-REPLACEMENT}替换${*:--}

$ third_party_bash_script
REPLACEMENT

$ third_party_bash_script a b c
a b c

$ echo 'a b c' | third_party_bash_script
REPLACEMENT

我猜在 OP 的实际脚本中,$files 变量还有更多操作,因此为了确定 ${*:--} 是如何处理的,我们需要查看实际的脚本及其引用 $files 变量的方式。


至于 OP 的 set|files=|echo 代码片段:

$ set one="1" two="2" three="3"
$ files="${*:--}"
$ echo $files
one=1 two=2 three=3

我们可以从脚本中看到相同的行为:

$ third_party_bash_script one="1" two="2" three="3"
one=1 two=2 three=3