Um pouco confuso sobre se printf no yash shell é um comando interno ou não

14

O yashshell possui um printfbuilt-in, de acordo com seu manual .

No entanto, é isso que vejo em um yashshell com configuração padrão:

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

É printfum embutido neste shell ou não? O resultado é semelhante para vários outros utilitários supostamente internos que também estão disponíveis como comandos externos.

Como comparação, em pdksh( kshno OpenBSD, onde nãoprintf é um built-in):

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

E em bash(onde printf é um built-in):

$ command -v printf
printf
$ type printf
printf is a shell builtin
Kusalananda
fonte
1
É um built-in - um regular , não um especial . Se você estiver confuso sobre a diferença entre built-ins especiais e regulares ou o comportamento exigido pelo padrão (consulte pesquisa e execução de comandos 1.eia) - que exige que um binário exista PATHpara que um built-in regular para ser executado - então faça sua pergunta sobre isso.
mosvy
1
@mosvy Este foi um detalhe do padrão que me era desconhecido. Se você quiser transformar isso em uma resposta, eu ficaria feliz. Acho que não precisaria atualizar a pergunta para que esta seja uma resposta apropriada, pois não tinha conhecimento desses detalhes em particular. Ou eu mesmo escreverei depois.
Kusalananda

Respostas:

14

O yashshell não tem, e faz uso, uma versão built-in de printf(e outros utilitários). Por acaso, é muito compatível com o POSIX, de maneira pedanástica, na maneira como formula o resultado dos comandos command -ve type.

Como comentários do mosvy , o padrão POSIX exige que um comando interno regular esteja disponível como um comando externo $PATHpara que a versão interna do comando seja executada.

Este é o texto relevante da norma :

Pesquisa e execução de comandos

Se um comando simples resultar em um nome de comando e uma lista opcional de argumentos, as seguintes ações deverão ser executadas:

  1. Se o nome do comando não contiver caracteres <slash>, ocorrerá a primeira etapa bem-sucedida da seguinte sequência:

    • uma. Se o nome do comando corresponder ao nome de um utilitário interno especial, esse utilitário interno especial será chamado.

      [...]

    • e Caso contrário, o comando deverá ser pesquisado usando a variável de ambiente PATH, conforme descrito em Variáveis ​​de ambiente XBD:
      • Eu. Se a pesquisa for bem sucedida:
        • uma. Se o sistema tiver implementado o utilitário como uma função embutida regular ou como uma shell, ele deverá ser chamado neste momento na pesquisa de caminho.
        • b. Caso contrário, o shell executa o utilitário em um ambiente utilitário separado [...]
          [...]
      • ii. Se a pesquisa não for bem sucedida, o comando falhará com um status de saída 127 e o shell deverá escrever uma mensagem de erro.
  2. Se o nome do comando contiver pelo menos um <slash>, [...]

Isso significa que a saída de command -v printfsignifica que o printfcomando foi encontrado no caminho de pesquisa, enquanto a saída de type printfacrescenta a isso que o comando é um built-in regular.

Como o printfcomando foi encontrado no caminho de pesquisa e como é um built-in regular no shell, yashele chamará sua versão interna do comando . Se nãoprintf foi encontrado no caminho e se o shell estivesse sendo executado no modo correto POSIX-ly, um erro teria sido gerado.yash

yashorgulha-se de ser um shell muito compatível com POSIX, e isso também é verdade se observarmos o que o POSIX diz sobrecommand -v :

-v

Escreva uma string na saída padrão que indique o nome do caminho ou comando que será usado pelo shell, no ambiente de execução do shell atual (consulte Ambiente de Execução do Shell ), para chamar command_name, mas não o chama command_name.

  • Utilitários, utilitários internos regulares , command_namesincluindo um <slash>caractere, e quaisquer funções definidas pela implementação encontradas usando a PATHvariável (conforme descrito em Pesquisa e execução de comandos ), devem ser escritas como nomes de caminho absolutos .
Kusalananda
fonte
3
Alguém sabe por que o POSIX tem esse requisito para que exista um comando externo antes de executar o comando interno?
studog 23/01/19
@studog Você pode fazer isso como uma nova pergunta separada, possivelmente referindo-se a esta resposta e / ou pergunta.
Kusalananda
6

O shell Watanabe possui três tipos de embutidos, descritos em detalhes em seu manual. Todos os comandos internos também estão listados lá, mas é preciso inferir que algo é um comando interno "regular" devido à ausência de qualquer nota dizendo que o comando é "especial" ou "semi-especial" construídas em. Os embutidos regulares não são marcados.

printfé um desses "regulares" embutidos. No modo nativo, é sempre invocado, independentemente de haver um comando externo encontrado por esse nome.

$ PATH = / usr / bin 
$ printf
printf: este comando requer um operando
$ tipo printf
printf: um arquivo embutido comum em / usr / bin / printf
$
$ PATH = / 
$ printf
printf: este comando requer um operando
$ tipo printf
printf: um built-in regular (não encontrado em $ PATH)
$

Mas quando a posixly-correctopção de shell é definida, é apenas um recurso interno se o comando externo puder ser encontrado no PATH.

$ set --posixly-correct
$
$ PATH = / usr / bin 
$ printf
printf: este comando requer um operando
$
$ PATH = / 
$ printf
yash: não existe esse comando `printf '
$

Na verdade, isso está em conformidade com o que a Especificação Unix Unificada diz e diz desde pelo menos 1997.

Difere do shell Z, do shell 93 Korn, do shell Bourne Again e do shell Debian Almquist, nenhum dos quais implementa ou documenta esse comportamento para os built-ins regulares. O shell Z, por exemplo, documenta que os embutidos regulares sempre são encontrados, antes da etapa que procura PATH. O mesmo acontece com o shell Debian Almquist. E é isso que todos os shells fazem, mesmo que sejam invocados como shnas opções de ativação do POSIX.

% / bin / exec -a sh zsh -c "CAMINHO = /; digite printf; printf"
printf é um shell embutido
zsh: printf: 1: argumentos insuficientes
% / bin / exec -a sh ksh93 -c "CAMINHO = /; digite printf; printf"
printf é um shell embutido
Uso: printf [opções] formato [string ...]
% / bin / exec -a sh bash --posix -c "CAMINHO = / tipo printf; printf"
printf é um shell embutido
printf: use: printf [-v var] formato [argumentos]
% / bin / exec -a sh dash -c "CAMINHO = /; digite printf; printf"
printf é um shell embutido
sh: 1: printf: uso: formato printf [arg ...]
% 

No entanto, não executar printfquando não estiver PATHativado é o comportamento do shell PD Korn, shell Heirloom Bourne e shell MirBSD Korn; porque eles não têm um printfbuilt-in em primeiro lugar. ☺

% / bin / exec -a sh `comando -v ksh` -c" PATH = /; tipo printf; printf "
printf não encontrado
sh: printf: não encontrado
% / bin / exec -a sh `comando -v oksh` -c" PATH = /; digite printf; printf "
printf não encontrado
sh: printf: não encontrado
% / bin / exec -a sh `comando -v jsh` -c" PATH = /; tipo printf; printf "
printf não encontrado
sh: printf: não encontrado
% / bin / exec -a sh mksh -c "CAMINHO = /; tipo printf; printf"
printf não encontrado
sh: printf: não encontrado
% ksh -c "tipo printf; printf"
printf é um alias rastreado para / usr / bin / printf
uso: formato printf [argumentos ...]
% oksh -c "tipo printf; printf"
printf é um alias rastreado para / usr / bin / printf
uso: formato printf [argumentos ...]
% jsh -c "tipo printf; printf"
printf está com hash (/ usr / bin / printf)
uso: formato printf [argumentos ...]
% mksh -c "tipo printf; printf"
printf é um alias rastreado para / usr / bin / printf
uso: formato printf [argumentos ...]
$
JdeBP
fonte
Boa! Obrigado por confirmar e por adicionar os bits específicos do shell ao meu conhecimento! Eu já gosto mais dessa concha.
Kusalananda
-1

A redação pode ser melhorada.

Se o shell estiver no modo posix set --posixly-correct::

Para embutidos regulares que não existem no PATH, isso é impresso:

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

Qual é uma descrição clara: é um interno, mas não há executável com o mesmo nome no PATH.

No entanto, para built-ins regulares cujo nome também existe no PATH, isso é impresso:

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

O que parece implicar que o executável em / bin / echo será executado (o que não será). Sugiro que uma alteração de atpara also found in PATH at:

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

faria uma descrição melhor. Talvez incluir isso entre parênteses (como a outra resposta) poderia torná-lo melhor.


No modo POSIX, nenhum built-in regular funcionará menos que também seja encontrado no PATH.

No entanto, ambos (POSIX) são especiais:

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

E o yash é semi-especial (não especial para POSIX):

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

builtins ainda funcionam.

Isaac
fonte