Uma variável não citada (como em $var) ou substituição de comando (como em $(cmd)ou `cmd`) é o operador split + glob em shells semelhantes a Bourne.
Ou seja, seu conteúdo é dividido de acordo com o valor atual da $IFSvariável especial (que por padrão contém os caracteres de espaço, tabulação e nova linha)
E então, cada palavra resultante dessa divisão está sujeita à geração do nome do arquivo (também conhecido como globbing ou expansão do nome do arquivo ), ou seja, elas são consideradas como padrões e são expandidas para a lista de arquivos que correspondem a esse padrão.
Assim for i in $(xrandr), em , $(xrandr)porque não está entre aspas, é dividido em seqüências de caracteres de espaço, tabulação e nova linha. E cada palavra resultante dessa divisão é verificada quanto a nomes de arquivos correspondentes (ou deixados como se não correspondam a nenhum arquivo) e forpassa por cima de todos eles.
Em for i in "$(xrandr)", não estamos usando o operador split + glob como a substituição de comando é citada; portanto, há uma passagem no loop em um valor: a saída de xrandr(sem os caracteres de nova linha à direita que comandam as tiras de substituição ).
No entanto echo $i, em , $ié sem aspas novamente, portanto, novamente o conteúdo de $ié dividido e sujeito à geração do nome do arquivo e esses são passados como argumentos separados para o echocomando (e echogera seus argumentos separados por espaços).
Então, lição aprendida:
- se você não deseja dividir palavras ou gerar nome de arquivo , sempre cite expansões variáveis e substituições de comandos
- se você deseja dividir palavras ou gerar nome de arquivo , deixe-os sem aspas, mas defina de
$IFSacordo 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 sobre a lista de palavras em branco e separadas na saída de xrandr, precisará:
- 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 que xrandrnunca gera nenhum *ou ?ou [caracteres (que são caracteres curinga usados nos padrões de geração de nome de arquivo)
E, em seguida, use apenas o operador split + glob (deixe apenas a substituição de comando ou a expansão variável sem aspas) na inparte do forloop:
set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done
Se você deseja fazer um loop sobre as linhas (não vazias) da xrandrsaída, precisará definir $IFSo caractere de nova linha:
IFS='
'