对yash shell中的printf是否是内置命令有点困惑

Kus*_*nda 15 posix shell-builtin printf yash

yash外壳有一个printf内置的,根据其说明书

但是,这是我在yash具有默认配置的shell 中看到的:

$ command -v printf
/usr/bin/printf
$ type printf
printf: a regular built-in at /usr/bin/printf
Run Code Online (Sandbox Code Playgroud)

printf这个shell中是否内置了?结果与许多其他假定的内置实用程序类似,这些实用程序也可用作外部命令。

作为对比,在pdkshksh在OpenBSD,这里printf不是内置的):

$ command -v printf
/usr/bin/printf
$ type printf
printf is /usr/bin/printf
Run Code Online (Sandbox Code Playgroud)

并在bash(其中printf 内置的):

$ command -v printf
printf
$ type printf
printf is a shell builtin
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 16

yash外壳确实有,而且不使用,内置的版本printf(和其他实用程序)。它恰好在制定command -vtype命令结果的方式上非常迂腐地符合 POSIX 。

正如 mosvy 评论的那样,POSIX 标准要求常规的内置命令可用作$PATH要执行的命令的内置版本的外部命令。

这是标准中的相关文本

命令搜索和执行

如果简单命令产生命令名称和可选参数列表,则应执行以下操作:

  1. 如果命令名称不包含任何 <slash> 字符,则应执行以下序列中的第一个成功步骤:

    • 一种。如果命令名称与特殊内置实用程序的名称匹配,则应调用该特殊内置实用程序。

      [...]

    • e. 否则,应使用 XBD 环境变量中所述的 PATH 环境变量搜索命令:
      • 一世。如果搜索成功:
        • 一种。如果系统已将该实用程序实现为常规内置函数或 shell 函数,则应在路径搜索的此时调用该实用程序。
        • 湾 否则,shell 将在单独的实用程序环境中执行该实用程序 [...]
          [...]
      • ii. 如果搜索不成功,命令将失败,退出状态为 127,shell 将写入错误消息。
  2. 如果命令名称至少包含一个 <slash>,则 [...]

这意味着输出的command -v printf表示该printf命令在搜索路径中找到,而输出type printf增加了这一点,该命令是一个普通的内置。

由于该printf命令是在搜索路径中找到的,并且由于它是 shell 中的常规内置yash命令,因此将调用命令的内置版本。如果printf没有在路径中发现,如果yash外壳在POSIX-LY正确的模式运行时,将已生成的错误信息。

yash以自己是一个非常符合 POSIX 的 shell 而自豪,如果我们看看POSIX 所说的内容command -v,这也是正确的:

-v

将一个字符串写入标准输出,指示 shell 将在当前 shell 执行环境(请参阅Shell 执行环境)中使用的路径名或命令来调用command_name,但不要调用command_name

  • 实用程序、常规内置实用程序command_names包括<slash>字符)以及使用PATH变量找到的任何实现定义的函数(如命令搜索和执行中所述应写为绝对路径名

  • 有谁知道为什么 POSIX 要求在运行内置命令之前存在外部命令? (4认同)
  • 完成:https://unix.stackexchange.com/questions/496341/why-does-posix-require-certain-shell-built-ins-to-have-an-external-implementatio (2认同)

Jde*_*eBP 6

Watanabe shell 有三种内置函数,在其手册中有详细描述。所有内置命令也都列在那里,但必须从没有任何注释说明该命令是“特殊”或“半特殊”的情况下推断某物是“常规”内置命令内置。常规内置插件没有标记。

printf是一种这样的“常规”内置。在本机模式下,它总是被调用,而不管是否有通过该名称找到的外部命令。

$ PATH=/usr/bin 
$ printf
printf:这个命令需要一个操作数
$输入 printf
printf:/usr/bin/printf 中的常规内置函数
$
$ PATH=/ 
$ printf
printf:这个命令需要一个操作数
$输入 printf
printf:常规内置(在 $PATH 中找不到)
$

但是当posixly-correct设置了shell 选项时,如果外部命令可以在PATH.

$ set --posixly-correct
$
$ PATH=/usr/bin 
$ printf
printf:这个命令需要一个操作数
$
$ PATH=/ 
$ printf
yash:没有这样的命令 `printf'
$

这实际上符合单一 Unix 规范所说的,并且至少从 1997 年开始就已经说过了。

它不同于 Z shell、93 Korn shell、Bourne Again shell 和 Debian Almquist shell,它们都没有实现或记录常规内置程序的此类行为。例如,Z shell 记录了搜索步骤之前总是可以找到常规内置函数的文档。Debian Almquist shell 也是如此。这就是这些 shell 所做的一切,即使调用它们的开启 POSIX 选项也是如此。PATHsh

% /bin/exec -a sh zsh -c "PATH=/ ; 输入 printf ; printf"
printf 是一个内置的 shell
zsh:printf:1: 没有足够的参数
% /bin/exec -a sh ksh93 -c "PATH=/ ; 输入 printf ; printf"
printf 是一个内置的 shell
用法:printf [选项] 格式 [字符串...]
% /bin/exec -a sh bash --posix -c "PATH=/ type printf ; printf"
printf 是一个内置的 shell
printf: 用法: printf [-v var] 格式 [参数]
% /bin/exec -a sh dash -c "PATH=/ ; type printf ; printf"
printf 是一个内置的 shell
sh: 1: printf: 用法: printf 格式 [arg ...]
% 

然而,printf当它不在时不运行是PATHPD Korn shell、Heirloom Bourne shell 和 MirBSD Korn shell 的行为;因为它们一开始就没有printf内置。☺

% /bin/exec -a sh `command -v ksh` -c "PATH=/ ; 输入 printf ; printf"
未找到 printf
sh:printf:未找到
% /bin/exec -a sh `command -v oksh` -c "PATH=/ ; type printf ; printf"
未找到 printf
sh:printf:未找到
% /bin/exec -a sh `command -v jsh` -c "PATH=/ ; 输入 printf ; printf"
未找到 printf
sh:printf:未找到
% /bin/exec -a sh mksh -c "PATH=/ ; 输入 printf ; printf"
未找到 printf
sh:printf:未找到
% ksh -c "输入 printf ; printf"
printf 是 /usr/bin/printf 的跟踪别名
用法:printf格式[参数...]
% oksh -c "输入 printf ; printf"
printf 是 /usr/bin/printf 的跟踪别名
用法:printf格式[参数...]
% jsh -c "输入 printf ; printf"
printf 被散列(/usr/bin/printf)
用法:printf格式[参数...]
% mksh -c "输入 printf ; printf"
printf 是 /usr/bin/printf 的跟踪别名
用法:printf格式[参数...]
$