STDIN 和传递给 command 的参数有什么区别?

ste*_*ang 23 pipe io-redirection arguments

我可以使用任一形式来执行该cat方法:

cat file_name
cat < file_name
Run Code Online (Sandbox Code Playgroud)

结果是一样的

然后我想以man格式执行stdin

man < file_name
Run Code Online (Sandbox Code Playgroud)

虽然file_name包含:

# file_name
cat
Run Code Online (Sandbox Code Playgroud)

但它弹出 What manual page do you want?而不是 execute man cat

我想知道为什么cat可以接受stdin作为参数但man不能。命令行参数和stdin?之间有什么区别?

use*_*332 23

您的问题与您使用的 shell 如何解析命令行上的用户输入密切相关。

如果在命令行中的第一个字是一个程序,位于一个特殊的文件夹(主要由定义PATH),并没有更多的特殊字符给出(取决于所使用的shell),所有后续单词分隔用空格或制表符被传递到该程序以特殊形式即数组。将每个单词作为数组中的一个元素。

您将要调用的程序如何解释参数(位于数组中)取决于它的编程方式。关于参数的语法应该是什么样子,有一些准标准,但总的来说,程序员是完全自由的。所以第一个参数可以解释为文件名或程序员在编写程序时的任何想法。

在这种情况下,你的特殊字符添加<>到命令行,外壳不到风度追加<>也没有后续的话,将被传递给程序的阵列。有了<>给定 shell 开始做一些奇特的事情,由底层内核支持(关键字pipe)。要掌握正在发生的事情,您必须了解是什么STDINSTDOUT(因为它不是直接相关的,我省略了STDERR)。

您在终端上看到的所有可见(在大多数情况下是显示器的一部分)都是由 shell 或您之前调用的任何其他程序写入特殊文件(在unix 中,一切都是文件)。这个文件有一个特殊的 id,叫做STDOUT. 如果程序想要从键盘读取数据,它不会直接轮询键盘(至少在大多数情况下),而是从名为STDIN. 在内部,此文件连接到您的标准输入设备,大多数情况下是您的键盘。

如果 shell 读取<>在解析的命令行中,它会在相应的程序运行时操作STDINSTDOUT以特定类型进行操作。STDIN并且STDOUT不再指向终端或标准输入设备,而是指向命令行上的后续文件名。

在两条线的情况下

cat file_name
cat < file_name
Run Code Online (Sandbox Code Playgroud)

观察到的行为是相同的,因为相应的开发人员会从文件中cat读取数据STDIN或从文件中读取数据,其名称作为第一个命令行参数给出(它是 shell 传递给的数组中的第一个元素cat)。随后catfile_name或的全部内容写入STDIN终端,因为我们没有指示外壳操作STDOUT. 请记住,在第二行中,您的 shellSTDIN以这种方式操作,它不再指向您的标准输入设备,而是指向file_name在您当前工作目录中调用的文件。

在该行的其他情况下

man < file_name
Run Code Online (Sandbox Code Playgroud)

manSTDIN如果不带参数(即空数组)调用它,则不打算从中读取任何内容。所以线

man < file_name
Run Code Online (Sandbox Code Playgroud)

等于

man
Run Code Online (Sandbox Code Playgroud)

例如,如果您传递给,也会man从 中读取某些内容。使用命令行上给出的此选项,您可以显示从终端读取的任何内容的内容。所以STDIN-l -manmanSTDIN

man -l - < file_name
Run Code Online (Sandbox Code Playgroud)

也可以工作(但要注意man不仅是寻呼机,还要分析文件的输入,因此文件内容和显示的内容可能不同)。

因此,如何STDINSTDOUT以及命令行参数被解释为全部达到相应的开发者。

我希望我的回答可以解决问题。

  • 我编辑了你的答案,因此它包含实际有用的链接而不是 lmgtfy。在 SE 网站上发布 lmgtfy 链接是 1) 粗鲁的,2) 无益的,3) [真的不受欢迎](http://meta.stackexchange.com/q/15650/203101)。要么提供链接,要么不提供,但如果您选择这样做,请提供指向实际信息的链接,而不是以讽刺的方式向某人展示如何找到它。 (2认同)

Mic*_*zek 12

他们完全不同。命令行参数以数组的形式传递给程序,它可以用它们做任何想做的事;stdin 是程序必须从中请求数据的输入流。处理文件的程序通常选择同时支持两者,但它们必须手动执行——它们检查文件名是否作为命令行参数传递,如果不是,则从 stdin 读取

您似乎希望man阅读 stdin 以找到它应该显示的手册页,这将是一种非常奇怪的行为;你什么时候会用它?这一事实cat显示其标准输入是,它并没有别的事实的假象; 我认为任何其他工具都不会这样工作。例如,grep可以采用文件名或从 读取stdin,但它处理 上的数据stdin,它不会从中读取文件名stdin然后打开它

如果您确实需要这种行为,则可以使用xargs,它将文件转换为命令行参数:

$ xargs man < file_name
Run Code Online (Sandbox Code Playgroud)

或者只是在cat通话中嵌入man通话:

$ man $(cat file_name)
Run Code Online (Sandbox Code Playgroud)