for i in $(xrandr); do echo "$i" ; done
for i in "$(xrandr)"; do echo "$i"; done
for i in "$(xrandr)"; do echo $i; done
Entendo por que 1 difere de 2. Mas por que 3 fornece uma saída diferente de 2? Por favor, explique a saída também. Como as cotações funcionam em novas linhas?
Respostas:
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
$IFS
variá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) efor
passa 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 dexrandr
(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 oecho
comando (eecho
gera seus argumentos separados por espaços).Então, lição aprendida:
$IFS
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 sobre a lista de palavras em branco e separadas na saída de
xrandr
, precisará:$IFS
em seu valor padrão (ou desative-o) para dividir em espaços em brancoset -f
para desativar a geração de nome de arquivo, a menos que você tenha certeza de quexrandr
nunca 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
in
parte dofor
loop:Se você deseja fazer um loop sobre as linhas (não vazias) da
xrandr
saída, precisará definir$IFS
o caractere de nova linha:fonte
Uma nova linha citada é uma nova linha. Portanto,
echo "$1"
fornece um único argumento de linha de comando para eco, que imprime as novas linhas diretamente.Uma nova linha não citada é um espaço em branco. Isso
echo $1
fornece muitos argumentos de linha de comando para eco, que os imprimem um após o outro separados por espaços.fonte