É possível imprimir a expansão do shell?

18

Eu sei que existe um conjunto específico de regras que expandem os comandos digitados pelo usuário. (Vamos falar sobre o bash shell.)

É possível imprimir um comando no formulário após a expansão do shell? Parece ser um bom utilitário para aprender e verificar como o shell expande caracteres especiais.

por exemplo

$ echo *

{all the filenames in current dir}

Quero imprimir o comando expandido, que é a seguinte linha:

echo {all the filenames in .}
Weishi Zeng
fonte

Respostas:

13

Basta usar echo... coloque-o na frente do comando que você deseja expandir. Eu uso isso com bastante frequência.

$ ls
one.txt
two.txt
three.dat
$ echo rm *.txt
rm one.txt two.txt
$ rm *.txt

Você pode usar Homee Deladicionar / remover rapidamente o anterior echo.

EDIT
Como apontou nos comentários, isso não vai funcionar se o comando não é apenas um simples comando (como se é um forloop, usa o tubo |, ou &&ou qualquer outra coisa parecida).

BenjiWiebe
fonte
11
Isto é o que eu faço quando testando um script
Barmar
Isso ainda é afetado por outros tokens de shell echo cat * | someprogramnão faz o que você pensa desta resposta.
Kroltan 6/01/15
13

Você pode usar set -x.

Por exemplo, considere o script:

$ cat script.sh
set -x
echo *

Quando executado, mostra a echoinstrução expandida antes de executá-la:

$ bash script.sh
+ echo file1 file2 file3 script.sh
file1 file2 file3 script.sh

E, como Kundor aponta, isso também funciona interativamente na linha de comando:

$ set -x
+ set -x
$ echo *
+ echo file1 file2 file3 script.sh
file1 file2 file3 script.sh

Documentação

man bashexplica o que set -xfaz o seguinte:

Depois de expandir cada comando simples, para comando, comando caso, selecione comando ou aritmética para comando, exiba o valor expandido do PS4, seguido pelo comando e seus argumentos expandidos ou lista de palavras associada.

O valor padrão para PS4é, como mostrado acima, um sinal de mais seguido por um espaço.

John1024
fonte
2
E funciona bem em um shell interativo, também (o que eu acho que o OP está procurando.)
Nick Matteo
7

Para um shell interativo, pressionar Ctrl+xe *depois de digitar o padrão glob editará sua linha de comando com esse padrão expandido. Na página do manual do bash:

palavra de expansão global ( C-x *)

A palavra antes do ponto é tratada como um padrão para a expansão do nome do caminho e a lista de nomes de arquivos correspondentes é inserida, substituindo a palavra. Se um argumento numérico for fornecido, um asterisco será anexado antes da expansão do nome do caminho.

Você também pode estar interessado em expansões da lista glob ( Ctrl+x, g).

jamesdlin
fonte
Estou usando o bash no Mac OS. Eu tentei ctrl + x, command + x. Não tenho certeza se ele faz alguma edição de linha de comando. você poderia elaborar mais?
Weishi Zeng
@WeishiZeng Não sei por que não está funcionando para você. Você pressionou Ctrl+x, *imediatamente após digitar echo *e antes de pressionar a tecla Enter? Se ainda assim não funcionar, você pode modificar ~/.inputrce vincular glob-expand-word a outra coisa.
jamesdlin
contrl + x move o cursor para a palavra eco, mas não edita nada. "Ctrl + x " , o que isso significa? (é ctrl + x OU ctrl + ??) * está no Shift, então eu preciso pressionar Shift também para obter um *, certo?
Weishi Zeng
Certo, pressione Ctrl+xseguido de Shift+8. Você pode tentar ver se Ctrl+x, gfunciona ou, como eu disse anteriormente, atribuir sua própria chave no .inputrcarquivo.
jamesdlin
1

Se quiser ver como os argumentos são expandidos ou tokenizados, você pode usar um programa ou script que imprima seus argumentos. Aqui está uma implementação em bash:

#!/bin/bash

for (( i = 0; i <= $#; ++i )); do
    printf 'argv[%d] = %s\n' $i "${!i}"
done

Supondo que você coloque isso em um arquivo chamado printargs.sh(e o torne executável), você obterá uma saída como esta

$ ./printargs.sh a{1..3}b
argv[0] = ./printargs.sh
argv[1] = a1b
argv[2] = a2b
argv[3] = a3b
jjlin
fonte