关于yash shell中的printf是否是内置命令有些困惑


14

根据其手册,该yash外壳具有printf内置功能。

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

kk@eeyore ~ $ command -v printf
/usr/bin/printf
kk@eeyore ~ $ type printf
printf: a regular built-in at /usr/bin/printf

是否printf在此外壳中内置?对于许多其他假定的内置实用程序(也可以作为外部命令使用),结果是相似的。

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

$ command -v printf
/usr/bin/printf
$ type printf
printf is /usr/bin/printf

而在bash(这里printf 一个内置的):

$ command -v printf
printf
$ type printf
printf is a shell builtin

1
它是内置的- 常规的,而不是特殊的内置。如果您对特殊内置和常规内置之间的区别感到困惑,或者对标准规定的行为感到困惑(请参阅命令搜索和执行 1.eia),这要求二进制文件应存在PATH以便常规内置待执行-然后请对此提出您的问题。
mosvy

1
@mosvy这是我所不知道的标准的细节。如果您想把它变成答案,我会很高兴。我认为我不需要更新这个问题来作为一个合适的答案,因为我不知道这个特定的细节。不然我稍后再写。
库萨兰达

Answers:


14

yash外壳确实具有并且确实使用了printf(和其他实用程序)的内置版本。这恰好是在路上很迂腐符合POSIX标准,其制定的结果command -vtype命令。

就像mosvy注释一样,POSIX标准要求常规的内置命令可用作$PATH要执行的内置版本的外部命令。

这是来自标准的相关文本

命令搜索和执行

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

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

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

      [...]

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

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

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

yash我们以成为POSIX兼容的外壳而感到自豪,如果我们看看POSIX所说的command -v话,这也是正确的:

-v

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

  • 实用程序,常规的内置实用程序command_names包括一个<slash>字符)以及使用该PATH变量找到的任何实现定义的功能(如Command Search and Execution中所述均应写为绝对路径名

3
有谁知道为什么POSIX要求在运行内置命令之前存在外部命令?
studog

@studog您可能想将其作为一个单独的新问题提出,可能是指此答案和/或问题。
库萨兰达


6

Watanabe外壳具有三种内置组件,在其手册中有详细介绍。所有内置命令也都在此处列出,但是必须从不存在的情况下推断出某种东西是“常规”内置命令任何说明该命令是“特殊”或“半特殊”内置的。常规内置程序未标记。

printf是一种这样的“常规”内置。在纯模式下,无论是否使用该名称找到了外部命令,总是会调用。

$  PATH = / usr / bin 
$ printf
printf:此命令需要一个操作数
$ type printf
printf:/ usr / bin / printf的常规内置文件
$
$ PATH = / 
$ printf
printf:此命令需要一个操作数
$ type printf
printf:常规内置文件(在$ PATH中找不到)
$

但是,如果posixly-correct设置了shell选项,则只能在上找到外部命令,这是内置命令PATH

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

这实际上与Single Unix规范所说的一致,并且至少从1997年开始就这样说。

它不同于Z外壳,93 Korn外壳,Bourne Again外壳和Debian Almquist外壳,它们都没有为常规内置程序实现或记录这种行为。例如,Z shell会搜索步骤之前始终找到常规内置文件。Debian Almquist外壳程序也是如此。这就是所有这些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 = /类型printf; printf”
printf是一个内置的shell
printf:用法:printf [-v var]格式[参数]
%/ bin / exec -a sh破折号-c“ PATH = /;输入printf; printf”
printf是一个内置的shell
sh:1:printf:用法:printf格式[arg ...]
% 

但是,PD Korn外壳,Heirloom Bourne外壳和MirBSD Korn外壳的行为printf是无法运行的PATH。因为它们首先没有printf内置功能。☺

/ bin / exec -a sh`命令-v ksh` -c“ PATH = /;输入printf; printf”
找不到printf
sh:printf:未找到
%/ bin / exec -a sh`命令-v oksh` -c“ PATH = /;输入printf; printf”
找不到printf
sh:printf:未找到
%/ bin / exec -a sh`命令-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格式[参数...]
$

好!感谢您的确认并向我添加了特定于shell的位!我已经更喜欢这个壳了。
Kusalananda

-1

措词可以改进。

如果外壳处于posix模式set --posixly-correct

对于PATH中不存在的常规内置程序,将输出:

pushd: a regular built-in (not found in $PATH)

这是一个清晰的描述:它是内置的,但PATH中没有同名的可执行文件。

但是,对于在PATH中也存在名称的常规内置文件,将显示以下内容:

echo: a regular built-in at /bin/echo

这似乎暗示/ bin / echo的可执行文件将被执行(不会)。我建议从at改为also found in PATH at

echo: a regular built-in also found in PATH at /bin/echo

会做出更好的描述。也许将其括在括号中(如其他答案一样)可能会更好。


在POSIX模式下,除非在PATH中找到常规内置函数,否则它将无法正常工作。

但是,两者(POSIX)都特别:

break colon continue dot eval exec exit export
readonly return set shift times trap unset

和yash的半专业版(不适用于POSIX):

alias bg cd command false fc fg getopts jobs
kill pwd read true umask unalias wait

内置仍然有效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.