什么是美元? (美元问号)shell 脚本中的变量? [复制]

Posted

技术标签:

【中文标题】什么是美元? (美元问号)shell 脚本中的变量? [复制]【英文标题】:What is the $? (dollar question mark) variable in shell scripting? [duplicate] 【发布时间】:2011-10-13 15:38:12 【问题描述】:

我正在尝试学习 shell 脚本,我需要了解别人的代码。 $? 变量保持是什么?我无法通过 Google 搜索答案,因为它们会屏蔽标点符号。

【问题讨论】:

一个好的谷歌搜索结果是“bash 美元问号” SymbolHound 适用于涉及特殊字符的搜索。示例:symbolhound.com/?q=%24%3F info bash 也可以,但不幸的是你不能只搜索“$?”,因为文档省略了$。转到“特殊参数”部分(3.4.2 版本 4.2)或搜索反引号-\$'(您必须转义 ?,因为搜索词是正则表达式)。 (我确信有一种方法可以在评论中添加文字反引号。) 谷歌搜索“bash 美元问号”的那一刻将这个 SO 问题作为第一个结果。不要怪我们。 @KeithThompson 你现在可能已经知道了,但是你可以使用\` (so you end up writing \\`` 来获得反引号)(以及\\\\\\` 来获得我刚刚写的内容) 【参考方案1】:

最后执行的命令返回的错误码。 0 = 成功

【讨论】:

【参考方案2】:

先前执行的进程的返回值。

10.4 获取程序的返回值

在 bash 中,程序的返回值存储在一个特殊的变量中 叫 $?。

这说明了如何捕获程序的返回值,我 假设目录dada 不存在。 (这也是 由迈克建议)

        #!/bin/bash
        cd /dada &> /dev/null
        echo rv: $?
        cd $(pwd) &> /dev/null
        echo rv: $?

更多详情请见Bash Programming Manual。

【讨论】:

有那么一瞬间,我以为rv: 是某种老式的选项列表,但结果却是被回显的文本。【参考方案3】:

$?是最后执行的命令的结果(退出代码)。

【讨论】:

【参考方案4】:

即最后执行的函数/程序/命令的退出状态。参考:

exit / exit status @ tldp.org Special Shell Variables @ tldp.org Special Characters @ tlpd.org

【讨论】:

【参考方案5】:

$? 用于查找最后执行的命令的返回值。 在 shell 中尝试以下操作:

ls somefile
echo $?

如果somefile存在(不管是文件还是目录),你会得到ls命令抛出的返回值,应该是0(默认“成功”返回值)。如果它不存在,你应该得到一个非 0 的数字。确切的数字取决于程序。

对于许多程序,您可以在相应的手册页中找到数字及其含义。这些通常被描述为“退出状态”,并且可能有自己的部分。

【讨论】:

不仅仅是错误代码。是任意命令返回的状态码。 如果文件不存在,返回值为2 如果找不到命令 127 返回 所以man $? 是您获取退出状态的朋友。调用 ((1==2));echo $? 在 bash 中返回 1。【参考方案6】:

最后一个命令的退出代码运行。

【讨论】:

【参考方案7】:

如果使用set -e,它非常适合在脚本退出的情况下进行调试。例如,将echo $? 放在导致它退出的命令之后并查看返回的错误值。

【讨论】:

【参考方案8】:

$? 是命令的退出状态,这样您就可以菊花链式连接一系列命令。

示例

command1 && command2 && command3

command2 将在 command1's $? 产生 success (0) 时运行,如果 command3command2 将产生 successcommand3 将执行

【讨论】:

【参考方案9】:

最小的 POSIX C 退出状态示例

要了解$?,您必须首先了解定义by POSIX 的进程退出状态的概念。在 Linux 中:

当进程调用exit 系统调用时,即使在进程终止后,内核也会存储传递给系统调用的值(int)。

退出系统调用由exit()ANSI C 函数调用,并且当您从main 执行return 时间接调用。

调用退出子进程(Bash)的进程,通常使用fork + exec,可以使用wait 系统调用检索子进程的退出状态

考虑一下 Bash 代码:

$ false
$ echo $?
1

C 的“等价物”是:

假.c

#include <stdlib.h> /* exit */

int main(void) 
    exit(1);

bash.c

#include <unistd.h> /* execl */
#include <stdlib.h> /* fork */
#include <sys/wait.h> /* wait, WEXITSTATUS */
#include <stdio.h> /* printf */

int main(void) 
    if (fork() == 0) 
        /* Call false. */
        execl("./false", "./false", (char *)NULL);
    
    int status;
    /* Wait for a child to finish. */
    wait(&status);
    /* Status encodes multiple fields,
     * we need WEXITSTATUS to get the exit status:
     * http://***.com/questions/3659616/returning-exit-code-from-child
     **/
    printf("$? = %d\n", WEXITSTATUS(status));

编译运行:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o bash bash.c
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o false false.c
./bash

输出:

$? = 1

在 Bash 中,当您按 Enter 键时,会像上面一样发生 fork + exec + wait,然后 bash 将 $? 设置为分叉进程的退出状态。

注意:对于像 echo 这样的内置命令,不需要生成进程,Bash 只需将 $? 设置为 0 即可模拟外部进程。

标准和文档

POSIX 7 2.5.2“特殊参数”http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02:

?扩展到最近管道的十进制退出状态(请参阅管道)。

man bash“特殊参数”:

shell 专门处理几个参数。这些参数只能被引用;不允许分配给他们。 [...]

?扩展到最近执行的前台管道的退出状态。

ANSI C 和 POSIX 建议:

0 表示程序成功

其他值:程序以某种方式失败。

确切的值可以指示失败的类型。

ANSI C 没有定义任何值的含义,POSIX 指定大于 125 的值:What is the meaning of "POSIX"?

Bash 使用 if 的退出状态

在 Bash 中,我们经常使用退出状态$? 来隐式控制if 语句,如下所示:

if true; then
  :
fi

true 是一个只返回 0 的程序。

以上等价于:

true
result=$?
if [ $result = 0 ]; then
  :
fi

在:

if [ 1 = 1 ]; then
  :
fi

[ 只是一个名称怪异的程序(以及行为类似的 Bash 内置程序),而 1 = 1 ] 它的参数,另请参阅:Difference between single and double square brackets in Bash

【讨论】:

以上是关于什么是美元? (美元问号)shell 脚本中的变量? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

shell 脚本常用命令

Shell--变量

当我们将命令放在美元符号和括号内时,shell 中的含义是啥: $(command)

linux的shell变量之美元符号

Shell 脚本常用命令

用户变量