Quando executo esses dois comandos, recebo
$ type cd
cd is a shell builtin
$ type if
if is a shell keyword
É claramente mostrado que cd
é um shell embutido e if
é uma palavra-chave do shell. Então, qual é a diferença entre shell embutido e palavra-chave?
command-line
Avinash Raj
fonte
fonte
Respostas:
Há uma forte diferença entre um builtin e uma palavra-chave, na maneira como o Bash analisa seu código. Antes de falarmos sobre a diferença, vamos listar todas as palavras-chave e componentes internos:
Builtins:
Palavras-chave:
Observe que, por exemplo,
[
é um builtin e essa[[
é uma palavra-chave. Usarei esses dois para ilustrar a diferença abaixo, pois são operadores bem conhecidos: todos os conhecem e os usam regularmente (ou deveriam).Uma palavra-chave é verificada e entendida pelo Bash muito cedo em sua análise. Isso permite, por exemplo, o seguinte:
Isso funciona bem, e o Bash terá uma saída feliz
Note que eu não citei
$string_with_spaces
. Considerando o seguinte:mostra que Bash não está feliz:
Por que funciona com palavras-chave e não com builtins? porque quando o Bash analisa o código, ele vê
[[
qual é uma palavra-chave e entende muito cedo que é especial. Por isso, procurará o fechamento]]
e tratará o interior de uma maneira especial. Um builtin (ou comando) é tratado como um comando real que será chamado com argumentos. Neste último exemplo, o bash entende que deve executar o comando[
com argumentos (mostrado um por linha):desde que ocorre expansão variável, remoção de cotação, expansão de nome de caminho e divisão de palavras. O comando
[
acaba sendo construído no shell, portanto, ele é executado com esses argumentos, o que resulta em um erro, daí a reclamação.Na prática, você vê que essa distinção permite um comportamento sofisticado, que não seria possível com os builtins (ou comandos).
Ainda na prática, como você pode distinguir um builtin de uma palavra-chave? este é um experimento divertido de executar:
Quando o Bash analisa a linha
$a -d . ]
, ele não vê nada de especial (ou seja, sem alias, sem redirecionamentos, sem palavras-chave), portanto, apenas realiza a expansão variável. Após expansões variáveis, ele vê:assim executa o comando (embutido)
[
com argumentos-d
,.
e]
, que, claro é verdadeiro (isto só testa se.
é um diretório).Agora veja:
Oh. Isso ocorre porque, quando o Bash vê essa linha, ele não vê nada de especial e, portanto, expande todas as variáveis e, eventualmente, vê:
No momento, há muito tempo que expansões de alias e verificação de palavras-chave são executadas e não serão mais executadas, então o Bash tenta encontrar o comando chamado
[[
, não o encontra e reclama.Na mesma linha:
e
A expansão de alias também é algo especial. Todos vocês fizeram o seguinte pelo menos uma vez:
O raciocínio é o mesmo: a expansão do alias ocorre muito antes da expansão variável e da remoção da cotação.
Alias vs palavra-chave
Agora, o que você acha que acontece se definirmos um alias para ser uma palavra-chave?
Oh, isso funciona! para que aliases possam ser usados para alias palavras-chave! bom saber.
Conclusão: builtins realmente se comportam como comandos: eles correspondem a uma ação sendo executada com argumentos que sofrem expansão direta de variável e divisão e globbing de palavras. É realmente como ter um comando externo em algum lugar
/bin
ou/usr/bin
é chamado com os argumentos dados após a expansão de variáveis, etc. Observe que quando digo é realmente como ter um comando externo quero dizer apenas com relação a argumentos, divisão de palavras, globbing, expansão variável, etc. Um builtin pode modificar o estado interno do shell!As palavras-chave, por outro lado, são verificadas e compreendidas muito cedo e permitem um comportamento sofisticado do shell: o shell poderá proibir a divisão de palavras ou a expansão do nome do caminho etc.
Agora, observe a lista de itens incorporados e palavras-chave e tente descobrir por que alguns precisam ser palavras-chave.
!
é uma palavra-chave. Parece que seria possível imitar seu comportamento com uma função:mas isso proibiria construções como:
ou
O mesmo para
time
: é mais poderoso ter uma palavra-chave para que possa programar comandos e pipelines compostos complexos com redirecionamentos:Se
time
onde um mero comando (mesmo embutido), seria só vê os argumentosgrep
,^#
e/home/gniourf/.bashrc
, tempo este, em seguida, sua saída seria percorrer as restantes partes do pipeline. Mas com uma palavra-chave, o Bash pode lidar com tudo! podetime
o pipeline completo, incluindo os redirecionamentos! Setime
fosse um mero comando, não poderíamos fazer:Tente:
Tente consertar (?):
Sem esperança.
Palavra-chave vs alias?
O que você acha que acontece?
Realmente, um builtin é como um comando, exceto que ele é construído no shell, enquanto uma palavra - chave é algo que permite um comportamento sofisticado! podemos dizer que faz parte da gramática do shell.
fonte
=\
'usandoman
,apropos
e,help
e eu não tive nenhuma sorte. Alguma idéia de onde eu iria encontrar essa informação? Principalmente para que no futuro eu possa ver o que mais existe, porque acho que estou perdendo uma fonte de referência.\ll
,"ll"
ou'll'
.[[
rendimento,\[[
ele não é analisado como um alias. Certo até agora? Onde eu me perdi não estava percebendo que a barra invertida era uma coisa citada no Bash, e tentei procurar por aliases e palavras-chave e me perdi completamente ... Tudo de bom agora. Na seção Citações:> Uma barra invertida não citada () é o caractere de escape.\[[
é um token único do tipo LiteralQuoteToken, em oposição ao[[
qual será um OpenTestKeywordToken, e que requer um]]
CloseTestKeywordToken de fechamento para compilação ou sintaxe correta. Posteriormente, em (4) o LiteralQuoteToken será avaliado[[
como o nome do bulitin / comando a ser executado e em (6) o Bash vomitará porque não há[[
comando ou construtor. Agradável. Posso esquecer os detalhes precisos ao longo do tempo, mas, neste momento, a maneira como o Bash executa as coisas é muito mais clara para mim; obrigado.man bash
liga para elesSHELL BUILTIN COMMANDS
. Portanto, um "shell embutido" é como um comando normal, comogrep
etc., mas, em vez de estar contido em um arquivo separado, ele é incorporado ao próprio bash . Isso os faz executar com mais eficiência do que comandos externos.Uma palavra - chave também é "codificada no Bash, mas, diferentemente de um built-in, uma palavra-chave não é em si um comando, mas uma subunidade de uma construção de comando". Interpreto que isso significa que as palavras-chave não têm função sozinha, mas exigem comandos para fazer qualquer coisa. (A partir do link, outros exemplos são
for
,while
,do
, e!
, e há mais em minha resposta à sua outra pergunta.)fonte
[[ is a shell keyword
mas[ is a shell builtin
. Eu não tenho ideia do porquê.[
existia como comando separado na época.[[
não é especificado pelo padrão, então os desenvolvedores podem optar por incluí-lo como palavra-chave ou como incorporado.O manual da linha de comando que acompanha o Ubuntu não fornece uma definição de palavras-chave; no entanto, o manual on - line (veja a nota em anexo) e as especificações padrão da POSIX Shell Command Language referem-se a elas como "Palavras Reservadas" e ambas fornecem listas delas. Do padrão POSIX:
A chave aqui é que palavras-chave / palavras reservadas têm um significado especial porque facilitam a sintaxe do shell, servem para sinalizar certos blocos de código, como loops, comandos compostos, instruções de ramificação (if / case) etc. Eles permitem a formação de instruções de comando, mas por si só - não fazer nada, e, de fato, se você digitar palavras-chave como
for
,until
,case
- o shell vai esperar uma declaração completa, caso contrário - erro de sintaxe:No nível do código-fonte, as palavras reservadas para o bash são definidas em parese.y , enquanto os internos têm um diretório inteiro dedicado a eles.
Nota
O índice GNU mostra
[
como palavra reservada, no entanto, é um comando interno de fato.[[
pelo contrário, é uma palavra reservada.Consulte também: Diferenças entre palavra-chave, palavra reservada e incorporada?
fonte