/usr/bin/time
在讨论和内置 shell(bash 和 zsh)之间的差异时time
,有人提到可以使用\time
作为 get 的简写/usr/bin/time
。
起初,这似乎是一个很好的无辜捷径,但随后出现了一些问题:
- 为什么
t\ime
也有效? - 为什么要
\cd
更改目录,即使/usr/bin/cd
¹ 没有?
显然,\foo
不等于$(which foo)
。现在的问题是:
bash 和 zsh 中观察到的行为是否\foo
以任何方式包含在 shell 的 POSIX 定义中?如果是,为什么它的行为如此?
脚注 1:/usr/bin/cd
在我的系统上,
#!/bin/sh
builtin cd "$@"
答案1
t\ime
or \cd
(或 或"tim"e
或'cd'
或${-##*}time
以及${-+time}
您能想到的所有其他引用和扩展的组合,最终会解析为time
或cd
),就是:另一种编写cd
和 的方式time
。
cd
然而,这最终会在 shell 语法解析和解释时或time
稍后解决。特别是,这种情况发生在 shell 关键字识别之后很长时间,并且别名发生替换。
因此,当 shell 正在寻找其语言的关键字时,它不会被识别ti\me
为time
shell 关键字。所以:
ti\me echo test
shell 将被识别为简单命令,而不是time
关键字后跟简单命令。
然后将处理引用ti\me
(这里反斜杠引用了m
无论如何都不需要引用的字符,引用字符被删除,你得到time
)和time
命令将像任何其他命令一样进行查找(在 中的内置命令、函数和可执行文件列表中$PATH
。很可能会/bin/time
在这里)
对于, shell 语言中cd
没有关键字,只有一个内置命令(优先于您的)。但是,如果您确实为(例如)定义了别名,则同样如此。由于别名替换是很早就完成的,在删除引号之前,如果您有一个别名 for而没有别名(请注意,没有多少 shell 允许其中包含反斜杠的别名),然后编写:cd
cd
/usr/bin/cd
cd
alias cd=pushd
cd
\cd
\cd dir
您要确保您的cd
别名未被替换。
简而言之,引用命令名或其任何部分可以防止它被视为 shell 关键字(关键字如while
, for
, if
, {
...time
是 in 中的关键字一些仅 shell),并绕过您可能拥有的别名。
但是,它不会强制该命令解析为 中的可执行文件$PATH
,该命令仍然首先在其中搜索功能(你可以通过这样做来解决command time cmd...
)和内置(你可以通过这样做来解决这个问题env time cmd...
,尽管我不知道有一个具有内置time
命令的外壳)。
请注意,引用还会影响某些 shell 中typeset
// declare
/ export
...系列的特殊内置函数的行为。local
看局部变量赋值需要引号吗?了解详情。