为什么 ${#}、${##} 是 1 而 ${?}、${??} 和 ${!} 是 0 而 ${-} 是 569JNORXZghiklms

shi*_*hin 0 bash

我找到了以下内容,想知道在哪里可以找到手册:

? echo ${#}
1

? echo ${##}
1

? echo ${?}
0

? echo ${??}
0

? echo ${!}
0

? echo ${-}
569JNORXZghiklms

? echo ${--}
569JNORXZghiklms
Run Code Online (Sandbox Code Playgroud)

ilk*_*chu 10

在大约两个不同的地方,至少在 Bash 的手册中。这些应该是标准特性,并且在每个 shell 中都是相似的,即使${-}这里的实际值看起来像是来自 Zsh。

$ echo ${#}
1
$ echo ${?}
0
$ echo ${!}
0
$ echo ${-}
569JNORXZghiklms
Run Code Online (Sandbox Code Playgroud)

这些是特殊参数 #, ?, !, 和-,用可选的大括号扩展。使用$#, $?,$!$-将是相同的。还有一些其他特殊参数,它们的“名称”${foo}是单个非字母非数字字符,通常与 相同,$foo但在类似情况下需要大括号${foo}bar,因为$foobar将被视为${foobar}.

特别是,

  • $#是脚本或当前函数的位置参数或自变量的数量。试试fun() { echo $#; }; fun a b c;

  • $?是最后一个前台命令或管道 ( ls -l /doesnotexist; echo $?)的退出状态。

  • $!如果是最新的后台作业 ( sleep 2 & ps uax |grep $!),则为进程 ID ,以及

  • $-有效的set标志列表。(还有setoptZsh 中的一些标志。Zsh 似乎也给出$!0好像没有这样的工作,Bash 将其显示为未设置。)

$ echo ${##}
1
$ echo ${??}
0
$ echo ${--}
569JNORXZghiklms
Run Code Online (Sandbox Code Playgroud)

这些是特殊参数#?-,但包含额外的参数扩展操作。(我不知道怎么称呼它们,它们只是参数扩展的一部分。)

  • ${#parameter}parameter值的长度,所以当$#1(或0等)时,${##}1,和foo=abc${#foo}3

    (有点相关,${parameter#word}删除一个前缀,它将是参数的值,其中前导部分匹配的单词被删除(例如foo=abcdef; echo ${foo#??}给出,cdef因为?匹配任何一个字符)。特殊情况${##}可以解释为要么取长度,要么删除空前缀,但长度扩展在这里胜过。${parameter%word}是相同的,但它删除了尾随部分。)

  • ${parameter?word}是一个“检查是否设置”的扩展,如果它被设置,它会给出参数的值,否则会抛出一个错误,包含word给出的文本。$?始终设置,因此检查不会做太多事情,但请尝试unset foo; echo ${foo?unset value\!}.

  • ${parameter-word}是“默认值”扩展,如果设置了参数,则采用参数值,否则采用word$-始终设置,因此您可以获得它的价值。但如果foo没有设置,${foo-bar}将是bar

最后两个和其他类似的有带有冒号${parameter:?word}和的变体,${parameter:?word}参数设置为空字符串时也会触发。Bash 的手册在这里可能更清楚,它提到了文本中的差异,但没有列出没有冒号的形式。不过,POSIX 文本有一个不错的 table


这一事实#?-在这里有两种不同的含义仅仅是一个巧合,还是具有一组有限的特殊字符,并使用用于使用一个相当简洁的语法壳的结果。