来自 POSIX 2013:
“简单命令”是一系列可选的变量赋值和重定向,以任何顺序,可选地后跟单词和重定向,由控制操作符终止。
来自 Bash 手册:
简单命令是最常遇到的命令。它只是由空格分隔的单词,由 shell 的控制运算符之一终止。
我觉得 POSIX 的定义比 Bash 手册的定义更好。但我仍然不确定 POSIX 的定义:
如果我是正确的,那么简单命令的终止控制运算符不属于该命令,或者是吗?
定义中的两个“重定向”是否属于简单命令?
在“一系列可选变量赋值和重定向”中,变量赋值之后“重定向”会做什么?变量赋值不会写入 stdout 或 stderr,对吧?
“以任何顺序的可选变量赋值和重定向序列”中的“以任何顺序”是什么意思?
该定义为一个简单的命令建议了多少种可能性,它们是什么?
POSIX 和 Bash 的简单命令概念是否相同?
答案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
不使用上述任何一项;他们被视为坏榜样。
要点是重定向可以出现在命令的第一个单词(或命令中的任何单词)之前或之后,但它们的处理方式相同。
变量赋值可以出现在命令之前,以便仅在该命令的持续时间(范围)内设置环境变量。例如,
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"三天前")
“以任何顺序”指的是我所说的最后一句话,也是这样的事实
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
。所以小心!。
您可能想阅读:
在“一系列可选变量赋值和重定向”中?
这里可选的意思是可能有一个,两个,...五个等等或没有。
命令行中可能没有重定向或变量赋值。
它是“可选的”。
变量赋值不会写入 stdout 或 stderr,对吧?
不,当然不是,它们只是更改 shell 变量的值。
而且,如果它们位于命令之前,它们通常会影响命令的环境,然后当命令结束时,更改会被折回(通常)。
“以任何顺序的可选变量赋值和重定向序列”中的“以任何顺序”是什么意思?
从左到右的顺序就是顺序。不,按任何顺序放置分配和/或重定向并不完全相同。
简而言之:99.99% 的情况下您都需要变量赋值前命令。如上所述,重定向的内部顺序确实很重要。重定向可以(但我不建议您使用它们,这会使读取命令行变得混乱)放置在任何地方(在所使用的控制字符的限制内)。
对于一个简单的命令,定义提出了多少种可能性,
可能性?无尽。例如,我们假设:
- 任何选项都没有重复(较小的计数)。
- 可能的命令名称:10 个(每次仅选择一个)。
- 可能的重定向:5(是的,有 10 个基本重定向,而且很多时候最多有 99 个可能的文件描述符)让我们从 10 个中选择 5 个(顺序很重要)。
- 可能的参数:让我们从 20 个可能的选项中选取 3 个(顺序可能对命令很重要,但并非总是如此,让我们选择最少数量的选项并说顺序并不重要)。
变量赋值?让我们从 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 的简单命令概念是否相同?
可能是的(由于解释者使用的语言而导致变化)。再说一次,不值得努力挤压每一滴。