A parte do manual de Bash que você citou fala sobre
Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read.
Então os aliases são realmente um daqueles exemplos que mostram a diferença entre ler e executar uma linha!
Para esclarecer, aqui está um comando composto. Primeiro, tentamos definir um alias e tentamos usá-lo:
alias echo=uname; echo
Alguém que não esteja familiarizado com o Bash esperaria que a saída desse comando seja Linux
(ou qualquer sistema operacional que você esteja executando), mas na verdade ele não produz nada. Isso ocorre porque o Bash primeiro lê a linha e aplica definições de alias. Então é isso que o Bash vê:
alias echo=uname; echo
Observe que o segundo echo
não é convertido em uname
. Isso ocorre porque o Bash ainda não executou nosso comando alias echo=uname
, ele apenas o leu . Depois que o Bash leu a linha, ele executa o que leu. Por isso, executa:
alias echo=uname; echo
(que é exatamente o que lê, conforme descrito acima)
Podemos até checar se o Bash executou o comando digitando echo
. Como definimos um alias antes, echo
será convertido para uname
durante a etapa de leitura, então o Bash executará uname
.
Resumindo:
$ alias echo=uname; echo
$ echo
Linux
Editar:
Após a sua edição, você perguntou se há uma maneira de mostrar os resultados depois que o Bash lê uma linha de entrada, mas antes de executá-los. A resposta é sim, mas não é muito conveniente para o uso diário (no entanto, é certamente útil para entender o que está acontecendo dentro do shell).
Crie um arquivo com o seguinte conteúdo:
#!/bin/bash
shopt -s expand_aliases
trapped() {
echo "On line ${1}, Bash sees: $BASH_COMMAND"
}
trap 'trapped ${LINENO}' DEBUG
alias echo=uname; echo
echo
Em seguida, execute esse arquivo.
Aqui está uma explicação de como esse script está funcionando:
-
shopt -s expand_aliases
diz ao Bash para expandir aliases mesmo quando está no modo não interativo (como neste caso) - Em seguida, definimos uma função
trapped()
. Quando chamado, esta função irá imprimir o comando que é executado atualmente (junto com um número de linha, que é passado como parâmetro). - Chamamos
trap 'trapped ${LINENO}' DEBUG
. Isso diz ao Bash "sempre que você vir um sinal chamadoDEBUG
, executetrapped ${LINENO}
first.DEBUG
é um sinal gerado automaticamente pelo Bash antes de qualquer execução de um comando simples . Em outras palavras , antes que qualquer comando seja executado, nossa funçãotrapped()
é chamada. - Por fim, executamos alguns comandos para demonstração. No entanto, uma vez que temos uma armadilha,
trapped()
é executado antes de qualquer outra coisa acontecer, então o Bash imprime o que está prestes a ser executado. A variávelLINENO
é apenas um Bash embutido, que nos fornece o atual linenumber.
Se você quiser "executar" comandos sem executá-los e ainda ver o que o Bash lê, talvez você queira examinar a opção extdebug
no manual do Bash.