`\time`、`t\ime` 和 `\cd` 实际上是做什么的? (shell 中反斜杠的乐趣)

`\time`、`t\ime` 和 `\cd` 实际上是做什么的? (shell 中反斜杠的乐趣)

/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\imeor \cd(或 或"tim"e'cd'${-##*}time以及${-+time}您能想到的所有其他引用和扩展的组合,最终会解析为timecd),就是:另一种编写cd和 的方式time

cd然而,这最终会在 shell 语法解析和解释时或time稍后解决。特别是,这种情况发生在 shell 关键字识别之后很长时间,并且别名发生替换。

因此,当 shell 正在寻找其语言的关键字时,它不会被识别ti\metimeshell 关键字。所以:

ti\me echo test

shell 将被识别为简单命令,而不是time关键字后跟简单命令。

然后将处理引用ti\me(这里反斜杠引用了m无论如何都不需要引用的字符,引用字符被删除,你得到time)和time 命令将像任何其他命令一样进行查找(在 中的内置命令、函数和可执行文件列表中$PATH。很可能会/bin/time在这里)

对于, shell 语言中cd没有关键字,只有一个内置命令(优先于您的)。但是,如果您确实为(例如)定义了别名,则同样如此。由于别名替换是很早就完成的,在删除引号之前,如果您有一个别名 for而没有别名(请注意,没有多少 shell 允许其中包含反斜杠的别名),然后编写:cdcd/usr/bin/cdcdalias cd=pushdcd\cd

\cd dir

您要确保您的cd别名未被替换。

简而言之,引用命令名或其任何部分可以防止它被视为 shell 关键字(关键字如while, for, if, {...time是 in 中的关键字一些仅 shell),并绕过您可能拥有的别名。

但是,它不会强制该命令解析为 中的可执行文件$PATH,该命令仍然首先在其中搜索功能(你可以通过这样做来解决command time cmd...)和内置(你可以通过这样做来解决这个问题env time cmd...,尽管我不知道有一个具有内置time命令的外壳)。

请注意,引用还会影响某些 shell 中typeset// declare/ export...系列的特殊内置函数的行为。local局部变量赋值需要引号吗?了解详情。

相关内容