O que a parantesia e o sinal $ significam em echo $ (ls)

7

A saída de

# ls

e

# echo $(ls)

são os mesmos. O que exatamente significa o sinal $ e o parêntese?

Além disso, o que está acontecendo em um nível técnico que faz com que a saída desses dois comandos seja a mesma?

    
por user784637 04.12.2011 / 02:53

4 respostas

6

Esta é a substituição de comando para o bash.

  

A substituição de comandos permite a saída de um comando para substituir   comando em si. A substituição de comandos ocorre quando um comando é incluído   da seguinte forma:

 $(command) or

 'command'

link

Mais:

link

link

E um bom exemplo semelhante à sua pergunta:

link

    
por heartsmagic 04.12.2011 / 03:12
2

Quando o shell encontra o texto entre $( ) , ele:

  1. Leva para ser um comando e (como bodhi.zazen diz ) executa o comando em um subshell .
  2. Substitui a saída do comando, no lugar da expressão inteira (incluindo a abertura $( e fechamento ) ).

Como a resposta do heartsmagic explica, isso é uma das duas sintaxes disponíveis para substituição de comando .

"O que ... faz com que a saída desses dois comandos seja a mesma?"

É realmente incomum que a saída de ls seja exatamente igual à saída de echo $(ls) :

ek@Io:~/tmp$ ls
bar  foo
ek@Io:~/tmp$ echo $(ls)
bar foo

ls normalmente separa nomes de arquivos por dois ou mais espaços, ou uma nova linha. Isso nos ajuda a distingui-los mais facilmente, especialmente porque espaços em nomes de arquivos são um pouco comuns (mas vários espaços consecutivos, menos comuns).

Divisão de palavras

Quando eu corri echo $(ls) , aconteceu o seguinte.

  1. Substituição de comandos substituiu $(ls) por:

    bar
    foo
    

    Você pode se surpreender ao ouvir isso, já que provavelmente não é o que você vê quando você executa ls por si só! Essa disparidade em que ls saídas é explicada abaixo, mas na verdade não é o motivo pelo qual você acaba com um único espaço entre essas duas palavras. O mesmo aconteceria se $(ls) fosse substituído por bar foo (com dois espaços).

  2. Posteriormente, o shell executou divisão de palavras , tratando bar e foo como argumentos separados para o comando echo em vez de como um único argumento contendo espaços.

Quando echo recebe vários argumentos (exceto para opções como -n , que são tratados especialmente e não impressos de todo), imprime todos eles, com um único espaço entre argumentos subseqüentes. echo , em seguida, imprime uma nova linha (a menos que a opção -n tenha passado).

Assim, echo $(ls) mostra a saída como bar foo em vez de bar foo .

Se você executar ls e não listar nenhum arquivo, ou apenas um arquivo, a saída de ls será frequentemente igual à saída de echo $(ls) . Mesmo assim, nem sempre será o mesmo, como quando um nome de arquivo contém espaço em branco diferente de espaços isolados (simples):

ek@Io:~/tmp2$ touch 'my   file'
ek@Io:~/tmp2$ ls
my   file
ek@Io:~/tmp2$ echo $(ls)
my file

Quando ls imprime vários arquivos, sua saída provavelmente não será exatamente igual à saída de $(ls) . Da mesma forma:

  • echo a b e echo $(echo a b) produzem a mesma saída, mas
  • echo 'a b' e echo $(echo 'a b') não.

Isso é importante para saber sobre a substituição de comandos - as substituições de comandos sem aspas estão sujeitas à divisão de palavras .

Detecção de terminal

Se você quiser evitar a divisão de palavras, você pode colocar a expressão para substituição de comandos entre aspas duplas ( " ). Isso geralmente é suficiente e, em particular, funcionará com os exemplos echo -based acima, bem como o exemplo de ls em um diretório com uma única entrada contendo espaços:

ek@Io:~/tmp2$ echo "$(ls)"
my   file

No entanto, conforme observado acima, você pode se surpreender ao descobrir que o que vê quando executa ls geralmente não é o que é passado para echo no lugar de "$(ls)" :

ek@Io:~/tmp$ ls
bar  foo
ek@Io:~/tmp$ echo "$(ls)"
bar
foo

Isso ocorre porque ls verifica se a saída padrão é um terminal para decidir como formatar sua saída , quando a formatação da saída não for explicitamente especificada.

  • Quando stdout é um terminal, ls é gerado em colunas classificadas verticalmente, como ls -C .
  • Quando a stdout não é um terminal, ls lista cada entrada em sua própria linha, como ls -1 .

Na substituição do comando, a saída padrão não é um terminal porque a saída do comando não está sendo enviada diretamente para um terminal para você ver - em vez disso, ele está sendo capturado pelo shell e usado como parte de outro comando. / p>

Para obter a formatação de várias colunas ao executar ls por meio da substituição de comandos, passe o -C flag:

ek@Io:~/tmp$ echo "$(ls -C)"
bar  foo

( dir às vezes é sugerido como uma alternativa para ls -C e também funcionará para isso, embora dir se comporta como ls -C -b em vez de meramente ls -C .

Aliasing de shell

Outra razão pela qual ls às vezes pode se comportar de maneira diferente de echo "$(ls)" é que ls pode ser um alias do shell . Execute alias ls para verificar; no Ubuntu você normalmente recebe alias ls='ls --color=auto' , o que significa que quando ls aparece como a primeira palavra de um comando executado interativamente (e em algumas, mas não todas, outras circunstâncias), ele é substituído por ls --color=auto .

Por exemplo, quando executo ls , ele lista diretórios coloridos em azul e executáveis em verde (e implementa muitas outras regras de coloração também). --color=auto faz com que ls imprima a saída colorida quando a saída padrão é um terminal e não o contrário.

Para obter uma saída colorida ao executar ls via substituição de comando, passe a porcentagem co_de% ou --color opção . Se quiser, você pode combinar isso com --color=always :

echo $(ls -C --color)

Observe que, embora você possa tornar -C um alias para ls ou ls --color em vez de ls --color=always , e ls --color=auto não se importa se a saída padrão é um terminal ... esse alias ainda não será causa ls --color=always para produzir saída colorida quando chamada por substituição de comando. Isso ocorre porque os aliases de shell (em shells estilo Bourne gostam de bash ) são apenas expandidos quando o shell os vê como a primeira palavra de um comando (e eles não são herdados por subshells).

    
por Eliah Kagan 17.10.2014 / 02:48
1

() e $ () são usados para executar comandos em um subshell

Consulte o link para obter detalhes

    
por Panther 04.12.2011 / 02:59
0

Usar $ na frente de um nome de variável invoca o valor atribuído à variável. Eco sem o $ apenas imprimirá o nome da variável na tela (ou saída padrão).

    
por haziz 04.12.2011 / 07:22