如何理解一个简单命令的定义?

如何理解一个简单命令的定义?

来自 POSIX 2013:

“简单命令”是一系列可选的变量赋值和重定向,以任何顺序,可选地后跟单词和重定向,由控制操作符终止。

来自 Bash 手册:

简单命令是最常遇到的命令。它只是由空格分隔的单词,由 shell 的控制运算符之一终止。

我觉得 POSIX 的定义比 Bash 手册的定义更好。但我仍然不确定 POSIX 的定义:

  • 如果我是正确的,那么简单命令的终止控制运算符不属于该命令,或者是吗?

  • 定义中的两个“重定向”是否属于简单命令?

  • 在“一系列可选变量赋值和重定向”中,变量赋值之后“重定向”会做什么?变量赋值不会写入 stdout 或 stderr,对吧?

  • “以任何顺序的可选变量赋值和重定向序列”中的“以任何顺序”是什么意思?

  • 该定义为一个简单的命令建议了多少种可能性,它们是什么?

  • POSIX 和 Bash 的简单命令概念是否相同?

答案1

添加格雷格的答案:

  1. 是的,两个重定向组 属于同一个简单命令。

    当我运行输入(stdin)和输出(stdout)重定向的命令时,我这样做:

    cmd 参数1  参数2  <文件1  >文件2

    有些人(少数人)主张

    <文件 1 cmd 参数1  参数2  >文件2

    变化,因为他们认为指定输入更直观,然后行动,以及然后输出。但以下内容都是等效的:

    <文件1  >file2 cmd 参数1  参数2
    >file2 cmd 参数1  参数2  <文件1
    指令  >文件 2 参数1  <文件 1 参数2

    使用上述任何一项;他们被视为坏榜样。

    要点是重定向可以出现在命令的第一个单词(或命令中的任何单词)之前或之后,但它们的处理方式相同。

  2. 变量赋值可以出现在命令之前,以便仅在该命令的持续时间(范围)内设置环境变量。例如,

    TZ=GMT0 ls -l

    列出您的文件,显示修改时间(格林威治标准时间)。 “可选的变量赋值和重定向,以任何顺序”意味着

    TZ=GMT0 ls -l > ls_输出_文件
    TZ=GMT0 > ls_输出_文件 ls -l
    > ls_output_file TZ=GMT0 ls -l

    都是等价的。再次,使用除第一个之外的任何一个。

    重点是变量赋值不能出现在命令的第一个单词之后;如果这样做,它们将被视为命令的参数。例如,查看 的语法dd

    变量赋值不会写入 stdout 或 stderr,对吧?

    简单的、常量的数据分配不进行任何处理(shell 内的簿记不算)。但是命令替换运行一个命令;CURRENT_DATE=$(date +%Y%m%d) 运行命令date +%Y%m%d ,其标准输出重定向到 shell 的管道,shell 捕获输出并将其嵌入到命令行中。但命令的stderrdate仍然是shell的stderr;如果您说OLD_DATE=$(date --date"three days ago"),您将在屏幕上收到一条错误消息,因为date不支持指定日期的语法。当然你可以抑制它,如果你说

    OLD_DATE=$(date --date"三天前" 2> /dev/null)

    但如果你说的话就不会

    OLD_DATE=$(date --date"三天前") 2> /dev/null

    或者

    2> /dev/null OLD_DATE=$(date --date"三天前")
  3. “以任何顺序”指的是我所说的最后一句话,也是这样的事实

    TZ=GMT0 列=132 ls -l

    相当于

    列=132 TZ=GMT0 ls -l

    (可能会有奇怪的边缘情况;我们不要冒险去那里。)

答案2

bash 手动定义至少是一个更简单的定义。重定向是一项独立于命令类型但与之相关的功能。重定向属于命令,因为它们影响与其关联的特定命令,但它们也可以与复杂命令一起出现(在子 shell 或组或管道中)。 POSIX 定义将许多概念塞进一个小空间,将它们分开(就像bash手册页那样)可能更容易理解。话说回来...

  • 终止控制运算符不是命令的一部分,它将简单命令与其他简单命令分开。

  • 重定向属于简单命令,可以有两个以上。

  • 重定向在某种程度上独立于命令文本,尽管在开始复制描述符时顺序很重要。对于你的例子,我将跳过这个概念。

    a=5 5> out5.file some-command > out.file arg1 2> out2.file arg 3> out3.file

    将是一个有效的简单命令。重定向可以散布在参数中并且可以按任何顺序出现。

  • 有多少种可能性?不确定你在这里问什么。有很多命令和无限的参数组合以及各种重定向,因此有很多可能性。

  • 是的,它们是相同的,但是 POSIX 将重定向的概念混入了定义中。

手册bash页是一个很好的资源。不过,我最喜欢的资源是 GNUBash 参考手册在 GNU.org 网站上。这是一个很好的进展,写得很好,几乎没有重复。查看简单命令定义和重定向部分,了解所有这些的更多详细信息。

答案3

只是解决出现的问题:

简单命令的终止控制运算符不属于该命令,是吗?

嗯,不。但它是界定“简单命令”的语法的一部分。没有适当控制分隔符的“简单命令”将无法被 shell 正确识别。
如果你问的是执行命令时是否执行分隔符控制字符,那么:。分隔符不是执行命令的一部分。

定义中的两个“重定向”是否属于简单命令?

从技术上讲,不会:重定向会影响命令执行的环境,因此:不是命令的“确切”部分。但从技术上讲,它们确实通过改变环境来影响正在执行的命令。

所以,有人可能会说:“有点”。

在“一系列可选变量赋值和重定向”中,变量赋值之后“重定向”会做什么?变量赋值不会写入 stdout 或 stderr,对吧?

哎呀,真是一口。让我们把它分成几部分:

变量赋值后“重定向”会做什么,

与之前完全相同,可以在整个命令行的中间、末尾或任何部分。简而言之:位置不会影响重定向的工作方式。

需要注意的是:重定向的顺序本身确实会改变它们对命令的影响。简而言之,它不>file 2>&1一样2>&1 >file。所以小心!。

您可能想阅读:

  1. 在shell中,“2>&1”是什么意思?
  2. 8.13 是“2>&1 文件”还是“>文件2>&1”?为什么?

在“一系列可选变量赋值和重定向”中?

这里可选的意思是可能有一个,两个,...五个等等或没有
命令行中可能没有重定向或变量赋值。
它是“可选的”。

变量赋值不会写入 stdout 或 stderr,对吧?

不,当然不是,它们只是更改 shell 变量的值。
而且,如果它们位于命令之前,它们通常会影响命令的环境,然后当命令结束时,更改会被折回(通常)。

“以任何顺序的可选变量赋值和重定向序列”中的“以任何顺序”是什么意思?

从左到右的顺序就是顺序。不,按任何顺序放置分配和/或重定向并不完全相同。
简而言之:99.99% 的情况下您都需要变量赋值命令。如上所述,重定向的内部顺序确实很重要。重定向可以(但我不建议您使用它们,这会使读取命令行变得混乱)放置在任何地方(在所使用的控制字符的限制内)。

对于一个简单的命令,定义提出了多少种可能性,

可能性?无尽。例如,我们假设:

  1. 任何选项都没有重复(较小的计数)。
  2. 可能的命令名称:10 个(每次仅选择一个)。
  3. 可能的重定向:5(是的,有 10 个基本重定向,而且很多时候最多有 99 个可能的文件描述符)让我们从 10 个中选择 5 个(顺序很重要)。
  4. 可能的参数:让我们从 20 个可能的选项中选取 3 个(顺序可能对命令很重要,但并非总是如此,让我们选择最少数量的选项并说顺序并不重要)。
  5. 变量赋值?让我们从 10 个可能的变量中选取 3 个。 (是的,一个非常低的数字)。

    1C10 * 5P10 * 3C20 * 3C10 = 10 * 10!/(10-5)! * 20!/((20-3)!*3!) * 10!/((10-3)!3!) = 41,368,320,000

如果我的数学正确的话。那就是不是计算可以混合的单词。只是一个 KISS 计算。

无论如何,这是一个巨大的选择。

它们是什么?

我无法在简短的回答中列出它们。但即使我可以,值得吗?

坦率地说,蒂姆,不要试图榨干最后一滴柠檬,我确信这对您的健康没有好处:-)。只是说!

POSIX 和 Bash 的简单命令概念是否相同?

可能是的(由于解释者使用的语言而导致变化)。再说一次,不值得努力挤压每一滴。

相关内容