Uma variável sem aspas (como em $var ) ou substituição de comando (como em $(cmd) ou 'cmd' ) é o operador split + glob em shells similares a Bourne.
Ou seja, o conteúdo é dividido de acordo com o valor atual da variável $IFS special (que, por padrão, contém os caracteres space, tab e newline)
E cada palavra resultante dessa divisão está sujeita a geração de nome de arquivo (também conhecida como globbing ou expansão de nome de arquivo ), ou seja, eles são considerados padrões e são expandidos para a lista de arquivos que correspondem a esse padrão.
Portanto, em for i in $(xrandr) , o $(xrandr) , porque não está entre aspas, é dividido em sequências de espaço, tabulação e caracteres de nova linha. E cada palavra resultante dessa divisão é verificada quanto a nomes de arquivos correspondentes (ou deixada como está se eles não corresponderem a nenhum arquivo), e for faz um loop sobre todos eles.
Em for i in "$(xrandr)" , não estamos usando o operador split + glob como a substituição do comando é citada, portanto há uma passagem no loop no valor um : a saída de xrandr (sem os caracteres de nova linha à direita que comandam as tiras de substituição ).
No entanto, em echo $i , $i não é citada novamente, novamente o conteúdo de $i é dividido e sujeito a geração de nome de arquivo e esses são passados como argumentos separados para o echo comando (e echo exibe seus argumentos separados por espaços).
Então, lições aprendidas:
- se você não quiser divisão de palavras ou geração de nome de arquivo , sempre cite expansões de variáveis e substituições de comandos
- se você quiser dividir palavras ou geração de nome de arquivo , deixe-as sem aspas, mas defina
$IFSde acordo e / ou ative ou desative a geração de nome de arquivo, se necessário (set -f,set +f).
Normalmente, no seu exemplo acima, se você quiser fazer um loop pela lista de palavras separadas em branco na saída de xrandr , será necessário:
- deixe
$IFSem seu valor padrão (ou desative-o) para dividir em espaços em branco - Use
set -fpara desativar a geração de nome de arquivo, a menos que você tenha certeza de quexrandrnunca produzirá nenhum caractere*ou?ou[(que são curingas usados nos padrões de geração de nome de arquivo)
E, em seguida, use somente o operador split + glob (somente deixe a substituição do comando ou a expansão variável sem aspas) na parte in do loop for :
set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done
Se você quiser fazer um loop pelas linhas (não vazias) da saída xrandr , será necessário definir $IFS como o caractere de nova linha:
IFS='
'