Leggermente confuso sul fatto che printf nella shell yash sia un comando incorporato o meno


14

La yashshell ha un printfbuilt-in, secondo il suo manuale .

Tuttavia, questo è quello che vedo in una yashshell con configurazione predefinita:

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

È printfintegrato in questa shell o no? Il risultato è simile per un certo numero di altre utilità apparentemente integrate che sono disponibili anche come comandi esterni.

A titolo di confronto, in pdksh( kshsu OpenBSD, dove nonprintf è incorporato):

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

E in bash(dove printf è incorporato):

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

1
È un built-in - un normale , non uno speciale incorporato. Se sei confuso sulla differenza tra built-in speciali e regolari o sul comportamento richiesto dallo standard (vedi ricerca comandi ed esecuzione 1.eia) - che richiede l'esistenza di un binario PATHper un normale built-in da eseguire - quindi ti preghiamo di porre la tua domanda al riguardo.
mosvy

1
@mosvy Questo era un dettaglio dello standard che mi era sconosciuto. Se vuoi trasformarlo in una risposta, sarei felice. Non credo che dovrei aggiornare la domanda affinché questa sia una risposta appropriata, poiché non ero a conoscenza di questo particolare dettaglio. O lo scriverò più tardi.
Kusalananda

Risposte:


14

Il yashguscio ha ha, e fa uso, una versione incorporata della printf(e altre utilità). Capita solo di essere molto compatibile con POSIX nel modo in cui formula il risultato dei comandi command -ve type.

Come commenta Mosvy , lo standard POSIX richiede che un comando incorporato regolare sia disponibile come comando esterno $PATHper l'esecuzione della versione integrata del comando.

Questo è il testo pertinente dello standard :

Ricerca ed esecuzione dei comandi

Se un comando semplice genera un nome comando e un elenco opzionale di argomenti, devono essere eseguite le seguenti azioni:

  1. Se il nome del comando non contiene caratteri <slash>, deve verificarsi il primo passaggio corretto nella sequenza seguente:

    • un. Se il nome del comando corrisponde al nome di un'utilità integrata speciale, deve essere invocata quell'utilità integrata speciale.

      [...]

    • e. Altrimenti, il comando deve essere cercato usando la variabile d'ambiente PATH come descritto in Variabili d'ambiente XBD:
      • io. Se la ricerca ha esito positivo:
        • un. Se il sistema ha implementato l'utilità come normale built-in o come funzione shell, deve essere invocata a questo punto nella ricerca del percorso.
        • b. Altrimenti, la shell esegue l'utilità in un ambiente di utilità separato [...]
          [...]
      • ii. Se la ricerca non ha esito positivo, il comando deve fallire con uno stato di uscita di 127 e la shell deve scrivere un messaggio di errore.
  2. Se il nome del comando contiene almeno un <slash>, [...]

Ciò significa che l'output di command -v printfindica che il printfcomando è stato trovato nel percorso di ricerca, mentre l'output di type printfaggiunge a ciò che il comando è un normale built-in.

Poiché il printfcomando è stato trovato nel percorso di ricerca e poiché è un normale built-in nella shell, yashchiamerà la sua versione integrata del comando . Se nonprintf fosse stato trovato nel percorso e se la yashshell fosse in esecuzione in modalità corretta POSIX, sarebbe stato invece generato un errore.

yashè orgoglioso di essere una shell molto conforme a POSIX, e questo vale anche se guardiamo a ciò che dice POSIX sucommand -v :

-v

Scrivere una stringa nell'output standard che indica il percorso o il comando che verrà utilizzato dalla shell, nell'ambiente di esecuzione della shell corrente (consultare Shell Execution Environment ), per invocare command_name, ma non invocare command_name.

  • Le utilità, le normali utilità integrate , command_namesincluso un <slash>carattere, e tutte le funzioni definite dall'implementazione che si trovano usando la PATHvariabile (come descritto in Ricerca comandi ed esecuzione ), devono essere scritte come nomi di percorso assoluti .

3
Qualcuno sa perché POSIX ha questo requisito per l'esistenza di un comando esterno prima di eseguire il comando integrato?
Studog

@studog Potresti porlo come una nuova domanda separata, eventualmente facendo riferimento a questa risposta e / o domanda.
Kusalananda


6

La shell Watanabe ha tre tipi di built-in, descritti in dettaglio nel suo manuale. Qui sono elencati anche tutti i comandi integrati, ma si deve dedurre che qualcosa è un comando incorporato "normale" dall'assenza di una nota che dice che il comando è un "speciale" o un "semi-speciale" built-in. I built-in regolari non sono contrassegnati.

printfè uno di questi "normale" incorporato. In modalità nativa viene sempre invocato, indipendentemente dal fatto che sia stato trovato un comando esterno con quel nome.

$ PATH = / usr / bin 
$ printf
printf: questo comando richiede un operando
$ type printf
printf: un normale built-in in / usr / bin / printf
$
$ PATH = / 
$ printf
printf: questo comando richiede un operando
$ type printf
printf: un normale built-in (non trovato in $ PATH)
$

Ma quando l' posixly-correctopzione shell è impostata, è solo integrata se il comando esterno può essere trovato su PATH.

$ set --posixly-correct
$
$ PATH = / usr / bin 
$ printf
printf: questo comando richiede un operando
$
$ PATH = / 
$ printf
yash: nessun comando `printf '
$

Questo è in realtà conforme a ciò che dice la specifica Unix singola, e lo ha detto almeno dal 1997.

Differisce dalla shell Z, dalla shell Korn 93, dalla shell Bourne Again e dalla shell Debian Almquist, nessuna delle quali implementa o documenta tale comportamento per i normali built-in. La shell Z, ad esempio, documenta che i normali built-in vengono sempre trovati, prima del passaggio di ricerca PATH. Lo stesso vale per la shell Debian Almquist. Ed è quello che fanno tutte queste shell, anche se invocate come shcon le loro opzioni POSIX di accensione.

% / bin / exec -a sh zsh -c "PATH = /; type printf; printf"
printf è una shell integrata
zsh: printf: 1: argomenti insufficienti
% / bin / exec -a sh ksh93 -c "PERCORSO = /; tipo printf; printf"
printf è una shell integrata
Utilizzo: printf [opzioni] formato [stringa ...]
% / bin / exec -a sh bash --posix -c "PATH = / type printf; printf"
printf è una shell integrata
printf: use: printf [-v var] format [argomenti]
% / bin / exec -a sh dash -c "PATH = /; type printf; printf"
printf è una shell integrata
sh: 1: printf: use: printf format [arg ...]
% 

Tuttavia, non è in esecuzione printfquando non è PATHpresente il comportamento della shell PD Korn, della shell Heirloom Bourne e della shell MirBSD Korn; perché non hanno un printfbuilt-in in primo luogo. ☺

% / bin / exec -a sh `command -v ksh` -c" PATH = /; type printf; printf "
printf non trovato
sh: printf: non trovato
% / bin / exec -a sh `command -v oksh` -c" PATH = /; type printf; printf "
printf non trovato
sh: printf: non trovato
% / bin / exec -a sh `command -v jsh` -c" PATH = /; type printf; printf "
printf non trovato
sh: printf: non trovato
% / bin / exec -a sh mksh -c "PATH = /; type printf; printf"
printf non trovato
sh: printf: non trovato
% ksh -c "type printf; printf"
printf è un alias tracciato per / usr / bin / printf
utilizzo: formato printf [argomenti ...]
% oksh -c "type printf; printf"
printf è un alias tracciato per / usr / bin / printf
utilizzo: formato printf [argomenti ...]
% jsh -c "type printf; printf"
printf è cancellato (/ usr / bin / printf)
utilizzo: formato printf [argomenti ...]
% mksh -c "type printf; printf"
printf è un alias tracciato per / usr / bin / printf
utilizzo: formato printf [argomenti ...]
$

Buona! Grazie per la conferma e per aver aggiunto i bit specifici della shell alla mia conoscenza! Mi piace più questa shell.
Kusalananda

-1

La formulazione potrebbe essere migliorata.

Se la shell è in modalità posix set --posixly-correct::

Per i normali built-in che non esistono nel PERCORSO, questo viene stampato:

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

Che è una chiara descrizione: è un builtin ma non esiste un eseguibile con lo stesso nome nel PERCORSO.

Tuttavia, per i normali built-in il cui nome esiste anche nel PERCORSO, viene stampato:

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

Il che sembra implicare che l'eseguibile in / bin / echo verrà eseguito (cosa che non sarà). Suggerisco di cambiare da ata also found in PATH at:

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

farebbe una descrizione migliore. Forse racchiuderlo tra parentesi (come ha fatto l'altra risposta) potrebbe renderlo migliore.


In modalità POSIX, nessun normale built-in funzionerà se non si trova anche nel PERCORSO.

Tuttavia, entrambi (POSIX) speciali:

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

E lo yash semi-speciale (non speciale per POSIX):

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

i builtin funzionano ancora.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.