yash シェルの printf が組み込みコマンドかどうかについて少し混乱しています

yash シェルの printf が組み込みコマンドかどうかについて少し混乱しています

シェルyashにはprintfマニュアルによると

yashただし、デフォルト設定のシェルでは次のようになります。

$ command -v printf
/usr/bin/printf
$ type printf
printf: a regular built-in at /usr/bin/printf

このシェルには組み込みユーティリティがありますprintfか? 結果は、外部コマンドとしても使用できる、組み込みユーティリティと思われる他の多くのユーティリティでも同様です。

比較として、OpenBSDのpdksh(では、kshprintfない組み込み):

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

そしてbashprintf 組み込み):

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

答え1

シェルyashするには、 (およびその他のユーティリティ) の組み込みバージョンがあり、実際にそれを使用しています。およびコマンドprintfの結果を作成する方法が、POSIX に厳密に準拠しているだけです。command -vtype

mosvyのコメント$PATHPOSIX 標準では、組み込みバージョンのコマンドを実行するには、通常の組み込みコマンドが外部コマンドとして使用可能であることが要求されています。

これは標準からの関連テキスト:

コマンドの検索と実行

単純なコマンドがコマンド名とオプションの引数リストを生成する場合、次のアクションが実行されます。

  1. コマンド名に <スラッシュ> 文字が含まれていない場合、次のシーケンスの最初の成功ステップが実行されます。

    • a. コマンド名が特別な組み込みユーティリティの名前と一致する場合、その特別な組み込みユーティリティが呼び出されます。

      [...]

    • e. それ以外の場合、コマンドはXBD環境変数で説明されているようにPATH環境変数を使用して検索されます。
      • 私。検索が成功した場合:
        • a.システムがユーティリティを通常の組み込み関数またはシェル関数として実装している場合は、パス検索のこの時点で呼び出されます。
        • b. それ以外の場合、シェルは別のユーティリティ環境でユーティリティを実行します [...]
          [...]
      • ii. 検索が失敗した場合、コマンドは終了ステータス 127 で失敗し、シェルはエラー メッセージを書き込みます。
  2. コマンド名に少なくとも 1 つの <スラッシュ> が含まれている場合、[...]

これは、出力がcommand -v printfコマンドprintfだった検索パスで見つかりますが、 の出力には、type printfコマンドが通常の組み込みコマンドであることがこれに追加されます。

コマンドprintfは検索パスで見つかり、シェルの通常の組み込みコマンドなので、yash組み込みバージョンのコマンドを呼び出す. もしそれprintfないパス内に見つからず、yashシェルが POSIX に正しいモードで実行されていた場合は、代わりにエラーが生成されます。

yashPOSIX準拠のシェルであることを誇りにしており、これはPOSIXが何について言っているかcommand -v:

-v

現在のシェル実行環境でシェルが使用するパス名またはコマンドを示す文字列を標準出力に書き出します(シェル実行環境) を呼び出すことはできますcommand_nameが、 を呼び出すことはできませんcommand_name

  • ユーティリティ、通常の組み込みユーティリティ(文字command_namesを含む<slash>)および変数を使用して見つかった実装定義の関数PATHコマンドの検索と実行)、絶対パス名として記述される

答え2

ワタナベシェルには3種類の組み込みコマンドがあり、マニュアルに詳細が説明されています。組み込みコマンドもすべてそこに記載されていますが、それが「通常の」組み込みコマンドであるかどうかは、不在コマンドが「特殊」または「半特殊」組み込みコマンドであることを示す注釈はありません。通常の組み込みコマンドにはマークがありません。

printfはそのような「通常の」組み込み関数の1つです。ネイティブモードではいつもその名前の外部コマンドが見つかったかどうかに関係なく、呼び出されます。

$PATH=/usr/bin
$プリント
printf: このコマンドにはオペランドが必要です
$printfと入力する
printf: /usr/bin/printf の通常の組み込み関数
$
$パス=/
$プリント
printf: このコマンドにはオペランドが必要です
$printfと入力する
printf: 通常の組み込み関数 ($PATH には存在しません)
$

ただし、posixly-correctシェル オプションが設定されている場合は、外部コマンドが で見つかる場合にのみ組み込みになりますPATH

$--posixly-correct を設定する
$
$PATH=/usr/bin
$プリント
printf: このコマンドにはオペランドが必要です
$
$パス=/
$プリント
yash: そのようなコマンド `printf' はありません
$

これは実際には Single Unix Specifiation の内容に準拠しており、少なくとも 1997 年以降はそう言われています。

これは、Zシェル、93 Kornシェル、Bourne Againシェル、Debian Almquistシェルとは異なります。これらのシェルはいずれも、通常の組み込み関数に対してこのような動作を実装または文書化していません。たとえば、Zシェルでは、通常の組み込み関数はいつも見つかった、前にを検索するステップPATHです。Debian Almquist シェルも同様です。そして、これらのシェルはすべて、shPOSIX をオンにするオプションで呼び出された場合でも、これを実行します。

%/bin/exec -a sh zsh -c "PATH=/ ; type printf ; printf"
printfはシェルの組み込み関数です
zsh:printf:1: 引数が足りません
%/bin/exec -a sh ksh93 -c "PATH=/ ; タイプ printf ; printf"
printfはシェルの組み込み関数です
使用法: printf [ オプション ] 形式 [ 文字列 ...]
%/bin/exec -a sh bash --posix -c "PATH=/ type printf ; printf"
printfはシェルの組み込み関数です
printf: 使用法: printf [-v var] フォーマット [引数]
%/bin/exec -a sh dash -c "PATH=/ ; type printf ; printf"
printfはシェルの組み込み関数です
sh: 1: printf: 使用法: printf フォーマット [arg ...]
%

ただし、PD Korn シェル、Heirloom Bourne シェル、および MirBSD Korn シェルでは、最初から が組み込まれていないためprintf、オンになっていないときに実行されないという動作になります。☺PATHprintf

%/bin/exec -a sh `command -v ksh` -c "PATH=/ ; type 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=/ ; type printf ; printf"
printf が見つかりません
sh: printf: 見つかりません
%/bin/exec -a sh mksh -c "PATH=/ ; type printf ; printf"
printf が見つかりません
sh: printf: 見つかりません
%ksh -c "type printf ; printf"
printfは/usr/bin/printfの追跡されたエイリアスです
使用法: printf 形式 [引数 ...]
%oksh -c "p​​rintf と入力; printf"
printfは/usr/bin/printfの追跡されたエイリアスです
使用法: printf 形式 [引数 ...]
%jsh -c "type printf ; printf"
printf はハッシュ化されます (/usr/bin/printf)
使用法: printf 形式 [引数 ...]
%mksh -c "type printf ; printf"
printfは/usr/bin/printfの追跡されたエイリアスです
使用法: printf 形式 [引数 ...]
$

関連情報