为什么这些 bash 命令的执行顺序很重要?

为什么这些 bash 命令的执行顺序很重要?

关于 bash shell 似乎存在一些我无法理解的不一致之处。

如果我执行:

ls;date;time

三个查询的结果按顺序显示。

但是,在交换日期和时间位置时,会弹出一条错误消息。

因此如果我执行:

ls;time;date

错误信息显示:bash: syntax error near unexpected token 'date'

有人能解释一下吗?

答案1

管道中的命令time不是/usr/bin/time二进制文件,而是 bashtime内置的。man time与进行比较help time。您看到的错误是 bash 无法解析time的参数。这必须存在或为换行符。在您的第一个示例中,它是一个换行符,但在第二个示例中不存在。

另一方面,如果你要运行

ls;date;'time'

或者

ls;'time';date

引号'time'取消了该命令的保留字状态,因此 bash 可以毫无问题地解析该行。现在,它会解析列表中的三个命令,并按顺序执行这些命令,/usr/bin/time无论哪种情况,它都会报告使用错误。

附录

我们发现,虽然time ; date会产生错误,time ; ; date但不会。可能的解释是,time ;bash 将 解释为 等同于time <newline>。然后,表达式被解析为和time ; ; date的列表。time ;date

time ;这与和也是合法的观察结果一致time ; ;,第二个被解析为包含的单例列表,time ;后跟列表后允许的可选分号。

因此,解释为什么time ; date会产生错误的另一种方法bash: syntax error near unexpected token 'date'是,它time会消耗与 分隔的分号date。它之所以能做到这一点,是因为time是 bash 的保留字。

答案2

time在解析命令行时,Bash 将内置命令视为特例。

从 bash 手册页中可以看到,输入的行首先被分成一个列表:

pipeline ; pipeline

管道的位置为:

[time [-p]] [ ! ] command [ [|⎪|&] command2 ... ]

或者在我们的例子中,简单地说:

time command

即如果时间存在,则命令必须也會出席。

[有一种特殊情况允许time后面跟着换行符,但这并不适用于此处]

因此,在我们的例子中,我们有:

time;date

分为两个管道:

1. time
2. date

并且管道 1 格式不正确,因为我们没有time命令。因此出现错误。

请注意,命令time行在这里也不起作用:

$ /usr/bin/time;date
Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]

bash 按照预期将其解析为 2 个管道:

1. /usr/bin/time
2. date

然后/usr/bin/time拒绝在没有参数的情况下运行。请注意,这是一个错误,而/usr/bin/time不是来自 bash 的错误。

反引号之所以有效,是因为反引号不再time被解释为管道内的特殊元素。

即使用反勾:

`time`;date

它被解析为两个管道:

1. `time`
2. date

请记住,在我们的例子中,管道是:

[time] command

最初的问题是我们没有time命令,这是不允许的。但现在我们只需命令:

`time`

没有前面的time,因为反引号表示time被解释为命令,而不是前面的单词。

因此,bash 随后运行其内置命令time,无需任何参数,这是可以接受的。它不会产生任何输出,我们也不会看到任何错误。

注意:

`time`

实际上运行结果内置函数time,即它运行time内置函数在 stdout 上生成的任何内容。但由于time它本身不会向 stdout 写入任何内容,因此它似乎可以工作。

最后,据指出,这是有效的:

time ; ; date

遗憾的是我无法解释:)

相关内容