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


Answers:


40

:壳内置VS不存在::

所述: 壳内置命令存在(注意之间差外部和内置命令),其不执行任何操作; 就像true命令一样,它只会返回成功。在:内置的是标准的,由POSIX标准定义,它也被称为“零效用”。它通常用于测试或运行无限循环,如while : ; do ...;done

bash-4.3$ type :
: is a shell builtin

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

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

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

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

还要注意,它:可以接受命令行参数,即这样做是合法的:

: :

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


在除bash之外的炮弹中

请注意,格式在不同的外壳之间也可能有所不同。对于bashkshmksh行为是一致的。例如,Ubuntu的默认/bin/sh外壳程序(实际上是/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()函数,根据文档,该函数采用字符串参数,然后在冒号之后输出错误消息,然后在换行符之后输出。引用:

perror()函数应将通过符号errno访问的错误号映射到与语言有关的错误消息,该消息应按以下方式写入标准错误流:

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

  • 然后是错误消息字符串,后跟<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外壳中,:使用带goto语句(根据该线程上名为Perderabo的用户​​的说法,不是内置的外壳)。引用手册:

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

因此,您可以执行以下操作来制作无限循环脚本:

: repeat
echo "Hello World"
goto repeat

“ 3个冒号”的“ 3列”错字
Barmar

1
DOS command.com和Windows cmd.exe具有类似但相反的情况::明确地是goto标签(而不是命令),并且经常重新用作注释字符(例如:: This is a comment)。
grawity

54

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

$ 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

例如,请参阅内建冒号的目的是什么?


是的,这是最全面的评论..比我的更雄辩..更好的解释:D
John Orion

8

尝试使用其他不存在的命令,您会发现该命令:可以正常使用英语:

$ ---
---: command not found

6

添加的冒号是错误消息本身的一部分。如果输入一种,cd ow则结果为bash: cd: ow: No such file or directory,这表明该错误将多余的冒号放入: No such file or directory


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

第三是格式化的间隔

在bash中a :是空行void指令


4

您得到3个冒号,因为错误格式包含冒号:

bash: <command>: command not found
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.