为什么 bash 中两个冒号作为命令 (::) 的错误消息有三个冒号,但单个冒号却没有输出?

为什么 bash 中两个冒号作为命令 (::) 的错误消息有三个冒号,但单个冒号却没有输出?

如果我输入

::

进入 bash shell,我得到:

-bash: ::: command not found

但只有一个:导致没有输出。这是为什么呢?

答案1

最后一个冒号只是默认“未找到”消息的一部分:

$ x
x: command not found
$ ::
::: command not found

原因是单身的结肠不产生任何东西: 一个有效的命令 - 尽管它什么都不做(除了 return TRUE)。来自SHELL BUILTIN COMMANDS以下部分man bash

   : [arguments]
          No effect; the command does nothing beyond  expanding  arguments
          and  performing any specified redirections.  A zero exit code is
          returned.

你有时会在以下结构中看到它

while :
do
  something
done

例如内置命令冒号有什么用途?

答案2

:内置 shell 与不存在的shell::

: shell 内置命令存在(注意外部命令和内置命令之间的区别) 不执行任何操作;它只是返回成功,就像true命令一样。:内置是标准的,由 POSIX 标准定义,也称为“空实用程序”。它经常用于测试或运行无限循环,例如while : ; do ...;done

bash-4.3$ type :
: is a shell builtin

但是,::两个冒号字符组合在一起,在 shell 中会被解释为一个“单词”,并假定这是用户输入的命令。shell 将检查内置命令,然后检查变量中的任何目录是否PATH存在该命令。但是,既没有内置命令,:: 也没有外部命令::。因此,这会产生错误。

那么,错误的典型格式是什么?

<shell>: <command user typed>: error message

因此,您看到的不是 3 个冒号,而是您输入的粘贴到标准错误格式中的内容。

还要注意,:可以采用命令行参数,即执行以下操作是合法的:

: :

在这种情况下,shell 会将其视为两个“单词”,其中一个是命令,另一个是位置参数。这也不会产生错误!(另请参阅(本答案后面的)关于将 of:与位置参数一起使用的历史记录。)


在除 bash 之外的 shell 中

请注意,不同 shell 的格式也可能不同。对于bashksh和 ,mksh行为是一致的。例如,Ubuntu 的默认/bin/shshell(实际上是/bin/dash):

$ dash
$ ::
dash: 1: ::: not found

其中 1 是命令号(相当于脚本中的行号)。

csh相比之下根本不会产生任何错误消息:

$ csh
% ::
%

事实上,如果你运行strace -o csh.trace csh -c ::,文件中的跟踪输出csh.trace显示csh以退出状态 0 退出(无错误)。但tcsh确实输出了错误(但不输出其名称):

$ tcsh
localhost:~> ::
::: Command not found.

错误消息

一般来说,错误消息中的第一项应该是正在执行的进程或函数(您的 shell 尝试执行::,因此错误消息来自 shell)。例如,这里正在执行的进程是stat

$ stat noexist
stat: cannot stat 'noexist': No such file or directory

事实上,POSIX 定义了错误()函数,根据文档,它接受一个字符串参数,然后在冒号后输出错误消息,然后是换行符。引用:

perror() 函数将通过符号 errno 访问的错误号映射到与语言相关的错误消息,该消息将写入标准错误流,如下所示:

  • 首先(如果 s 不是空指针并且 s 指向的字符不是空字节),s 指向的字符串后跟冒号和<空格>。

  • 然后是错误消息字符串,后跟 <newline>。

从技术上讲,字符串参数perror()可以是任何东西,但当然为了清楚起见,它通常为函数名称或argv[0]

相比之下, GNU 有自己的一套用于错误处理的函数和变量,程序员可以使用它fprintf()进行stderr流式传输。如链接页面上的一个例子所示,可以这样做:

  fprintf (stderr, "%s: Couldn't open file %s; %s\n",
           program_invocation_short_name, name, strerror (errno));

历史回顾

在旧式 Unix 和 Thompson shell 中,:用于goto陈述(根据名为 Perderabo 的用户所说此主题不是内置的 shell)。手册中的引述:

在整个命令文件中搜索以 : 作为第一个非空白字符开头的行,后面跟着一个或多个空格,然后是标签。如果找到这样的行,goto 会将命令文件偏移量重新定位到标签后的行并退出。这会导致 shell 转到带标签的行。

因此,您可以做类似这样的事情来制作无限循环脚本:

: repeat
echo "Hello World"
goto repeat

答案3

尝试任何其他不存在的命令,您将看到它:在英语中发挥其正常作用:

$ ---
---: command not found

答案4

$ ::
bash: ::: command not found
$ kkkk
bash: kkkk: command not found

第三个是格式化的间隔

在 bash 中 a:是一个空行 void 指令

相关内容