Etwas verwirrt darüber, ob printf in der Yash-Shell ein eingebauter Befehl ist oder nicht


14

Die yashShell hat laut Handbuch eine printfeingebaute .

In einer yashShell mit Standardkonfiguration sehe ich jedoch Folgendes:

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

Ist printfeine in diese Shell eingebaut oder nicht? Das Ergebnis ist für eine Reihe anderer angeblich integrierter Dienstprogramme ähnlich, die auch als externe Befehle verfügbar sind.

Zum Vergleich: in pdksh( kshunter OpenBSD, woprintf es kein eingebautes gibt):

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

Und in bash(wo printf ist ein eingebautes):

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

1
Es ist ein eingebautes - ein reguläres , kein spezielles eingebautes. Wenn Sie verwirrt sind über den Unterschied zwischen speziellen und regulären integrierten Funktionen oder über das vom Standard vorgeschriebene Verhalten (siehe Befehlssuche und Ausführung 1.eia) - was erfordert, dass eine Binärdatei vorhanden sein PATHmuss, damit eine reguläre integrierte Funktion verwendet werden kann ausgeführt werden - dann stellen Sie bitte Ihre Frage dazu.
Mosvy

1
@mosvy Dies war ein Detail des Standards, das mir unbekannt war. Wenn Sie daraus eine Antwort machen möchten, würde ich mich freuen. Ich glaube nicht, dass ich die Frage aktualisieren müsste, um eine angemessene Antwort zu erhalten, da mir dieses spezielle Detail nicht bekannt war. Oder ich schreibe es mir später.
Kusalananda

Antworten:


14

Die yashShell hat und benutzt eine eingebaute Version vonprintf (und anderen Dienstprogrammen). Es ist einfach sehr pedantisch POSIX-konform, wie es das Ergebnis der Befehle command -vund formuliert type.

Wie Mücken KommentareDer POSIX-Standard , dass ein regulärer integrierter Befehl als externer Befehl $PATHfür die integrierte Version des Befehls verfügbar sein muss.

Dies ist der relevante Text aus der Norm :

Befehlssuche und -ausführung

Wenn ein einfacher Befehl zu einem Befehlsnamen und einer optionalen Liste von Argumenten führt, müssen die folgenden Aktionen ausgeführt werden:

  1. Wenn der Befehlsname keine <Schrägstrich> -Zeichen enthält, wird der erste erfolgreiche Schritt in der folgenden Reihenfolge ausgeführt:

    • ein. Wenn der Befehlsname mit dem Namen eines speziellen integrierten Dienstprogramms übereinstimmt, wird dieses spezielle integrierte Dienstprogramm aufgerufen.

      [...]

    • e. Andernfalls muss der Befehl unter Verwendung der Umgebungsvariablen PATH wie in XBD-Umgebungsvariablen beschrieben durchsucht werden:
      • ich. Wenn die Suche erfolgreich ist:
        • ein. Wenn das System das Dienstprogramm als reguläre integrierte Funktion oder als Shell-Funktion implementiert hat, wird es an dieser Stelle in der Pfadsuche aufgerufen.
        • b. Andernfalls führt die Shell das Dienstprogramm in einer separaten Dienstprogrammumgebung aus [...]
          [...]
      • ii. Wenn die Suche nicht erfolgreich ist, schlägt der Befehl mit dem Beendigungsstatus 127 fehl und die Shell schreibt eine Fehlermeldung.
  2. Wenn der Befehlsname mindestens einen <Schrägstrich> enthält, [...]

Dies bedeutet , dass der Ausgang des command -v printfbedeutet , dass der printfBefehl wurde im Suchpfad gefunden, während der Ausgang destype printf dazu fügt hinzu , dass der Befehl ein reguläres ist eingebaut.

Da der printfBefehl im Suchpfad gefunden wurde und regelmäßig in die Shell integriert ist, yashwird die integrierte Version des Befehls aufgerufen . Wenn das printfwar nicht in dem Pfad, und wenn die yashSchale wurde in POSIX-ly korrekten Modus ausgeführt wird , wäre ein Fehler aufgetreten stattdessen erzeugt.

yashist stolz darauf, eine sehr POSIX-konforme Shell zu sein, und dies gilt auch, wenn wir uns anschauen, was POSIX über Folgendes aussagtcommand -v :

-v

Schreiben Sie eine Zeichenfolge in die Standardausgabe, die den Pfadnamen oder Befehl angibt, der von der Shell in der aktuellen Shell-Ausführungsumgebung (siehe Shell-Ausführungsumgebung ) zum Aufrufen command_name, aber nicht zum Aufrufen verwendet wird command_name.

  • Dienstprogramme, reguläre integrierte Dienstprogramme , command_nameseinschließlich eines <slash>Zeichens, und alle implementierungsdefinierten Funktionen, die mithilfe der PATHVariablen gefunden werden (wie in Befehlssuche und -ausführung beschrieben ), müssen als absolute Pfadnamen geschrieben werden .

3
Weiß jemand, warum für POSIX diese Anforderung besteht, dass ein externer Befehl vorhanden ist, bevor der integrierte Befehl ausgeführt wird?
Studog

@studog Möglicherweise möchten Sie dies als separate neue Frage stellen, wobei Sie sich möglicherweise auf diese Antwort und / oder Frage beziehen.
Kusalananda


6

Die Watanabe-Shell verfügt über drei Arten von integrierten Funktionen, die ausführlich in ihrem Handbuch beschrieben werden. Alle der integrierten Befehle auch dort aufgeführt sind, aber man hat , dass etwas eine „reguläre“ integrierten Befehl aus dem schließen Fehlen jeglicher Notiz, dass der Befehl ein „special“ oder ein „semi-special“ eingebaut. Normale Einbauten sind nicht markiert.

printfist eine solche "normale" eingebaut. Im einheitlichen Modus wird es immer aufgerufen, unabhängig davon, ob ein externer Befehl mit diesem Namen gefunden wurde.

$ PATH = / usr / bin 
$ printf
printf: Dieser Befehl erfordert einen Operanden
$ Typ printf
printf: ein reguläres eingebautes in / usr / bin / printf
$
$ PATH = / 
$ printf
printf: Dieser Befehl erfordert einen Operanden
$ Typ printf
printf: ein reguläres eingebautes (nicht in $ PATH gefunden)
$

Wenn die posixly-correctShell-Option aktiviert ist, ist sie nur dann integriert, wenn der externe Befehl auf der gefunden werden kann PATH.

$ set --posixly-correct
$
$ PATH = / usr / bin 
$ printf
printf: Dieser Befehl erfordert einen Operanden
$
$ PATH = / 
$ printf
yash: kein solcher Befehl `printf '
$

Dies entspricht den Aussagen der Single Unix Specifiation und ist seit mindestens 1997 bekannt.

Es unterscheidet sich von der Z-Shell, der 93-Korn-Shell, der Bourne-Again-Shell und der Debian-Almquist-Shell, von denen keine ein solches Verhalten für reguläre Einbauten implementiert oder dokumentiert. Die Z-Shell zum Beispiel dokumentiert, dass reguläre eingebaute Funktionen immer vor dem Schritt gefunden werden, der durchsucht wird PATH. Dies gilt auch für die Debian-Almquist-Shell. Und genau das tun diese Shells, auch wenn sie shmit ihren POSIX-Einschaltoptionen aufgerufen werden .

% / bin / exec -a sh zsh -c "PFAD = /; Typ printf; printf"
printf ist eine eingebaute Shell
zsh: printf: 1: nicht genug Argumente
% / bin / exec -a sh ksh93 -c "PFAD = /; Typ printf; printf"
printf ist eine eingebaute Shell
Verwendung: printf [options] format [string ...]
% / bin / exec -a sh bash --posix -c "PATH = / type printf; printf"
printf ist eine eingebaute Shell
printf: usage: printf [-v var] format [arguments]
% / bin / exec -a sh Gedankenstrich -c "PATH = /; Typ printf; printf"
printf ist eine eingebaute Shell
sh: 1: printf: usage: printf format [arg ...]
% 

Das Verhalten der PD-Korn-Shell, der Heirloom-Bourne-Shell und der MirBSD-Korn-Shell printfist jedoch nicht aktiv, wenn sie nicht PATHaktiviert ist. weil sie gar nicht erst printfeingebaut haben . ☺

% / bin / exec -a sh `Befehl -v ksh` -c" PATH = /; Typ printf; printf "
printf nicht gefunden
sh: printf: nicht gefunden
% / bin / exec -a sh `Befehl -v oksh` -c" PATH = /; Typ printf; printf "
printf nicht gefunden
sh: printf: nicht gefunden
% / bin / exec -a sh `Befehl -v jsh` -c" PATH = /; Typ printf; printf "
printf nicht gefunden
sh: printf: nicht gefunden
% / bin / exec -a sh mksh -c "PFAD = /; Typ printf; printf"
printf nicht gefunden
sh: printf: nicht gefunden
% ksh -c "Typ printf; printf"
printf ist ein nachverfolgter Alias ​​für / usr / bin / printf
Verwendung: printf Format [Argumente ...]
% oksh -c "Typ printf; printf"
printf ist ein nachverfolgter Alias ​​für / usr / bin / printf
Verwendung: printf Format [Argumente ...]
% jsh -c "Typ printf; printf"
printf ist gehasht (/ usr / bin / printf)
Verwendung: printf Format [Argumente ...]
% mksh -c "Typ printf; printf"
printf ist ein nachverfolgter Alias ​​für / usr / bin / printf
Verwendung: printf Format [Argumente ...]
$

Gut! Vielen Dank für die Bestätigung und für das Hinzufügen der Shell-spezifischen Bits meines Wissens! Ich mag diese Shell schon mehr.
Kusalananda

-1

Der Wortlaut könnte verbessert werden.

Wenn sich die Shell im Posix-Modus befindet set --posixly-correct:

Für reguläre Built-Ins, die im PATH nicht vorhanden sind, wird Folgendes gedruckt:

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

Was eine klare Beschreibung ist: Es ist eine eingebaute, aber es gibt keine ausführbare Datei mit demselben Namen im PATH.

Für reguläre Built-Ins, deren Name auch im PATH vorhanden ist, wird dies gedruckt:

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

Was bedeutet, dass die ausführbare Datei unter / bin / echo ausgeführt wird (was nicht der Fall sein wird). Ich schlage vor, dass ein Wechsel von atzu also found in PATH at:

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

würde eine bessere Beschreibung machen. Vielleicht könnte es besser sein, das in Klammern zu setzen (wie die andere Antwort es tat).


Im POSIX-Modus funktioniert kein reguläres Built-In, es sei denn, es befindet sich auch im PATH.

Beide (POSIX) -Spezial:

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

Und Yashs Semi-Special (nicht speziell für POSIX):

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

Builtins funktionieren immer noch.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.