Como alguém itera corretamente sobre linhas no bash em uma variável ou a partir da saída de um comando? Simplesmente definir a variável IFS como uma nova linha funciona para a saída de um comando, mas não ao processar uma variável que contém novas linhas.
Por exemplo
#!/bin/bash
list="One\ntwo\nthree\nfour"
#Print the list with echo
echo -e "echo: \n$list"
#Set the field separator to new line
IFS=$'\n'
#Try to iterate over each line
echo "For loop:"
for item in $list
do
echo "Item: $item"
done
#Output the variable to a file
echo -e $list > list.txt
#Try to iterate over each line from the cat command
echo "For loop over command output:"
for item in `cat list.txt`
do
echo "Item: $item"
done
Isso fornece a saída:
echo:
One
two
three
four
For loop:
Item: One\ntwo\nthree\nfour
For loop over command output:
Item: One
Item: two
Item: three
Item: four
Como você pode ver, ecoar a variável ou iterar sobre o cat
comando imprime cada uma das linhas uma por uma corretamente. No entanto, o primeiro loop for imprime todos os itens em uma única linha. Alguma ideia?
Respostas:
Com o bash, se você deseja incorporar novas linhas em uma sequência, coloque a sequência com
$''
:E se você já possui uma string em uma variável, pode lê-la linha por linha com:
fonte
done <<< "$list"
é crucialdone <<< "$list"
é crucial, porque isso passará "$ list" como entrada pararead
$list
são muito cruciais.echo "$list" | while ...
pode parecer mais claro do que... done <<< "$line"
Você pode usar
while
+read
:Btw. a
-e
opção paraecho
não é padrão. Use emprintf
vez disso, se você quiser portabilidade.fonte
<<<
versão sugerida por Glenn Jackman não trabalhar com atribuição de variável.while
peça. A<<<
versão não (em novas versões do bash, pelo menos).fonte
IFS=$'\n'
para o mesmo efeito.Aqui está uma maneira engraçada de fazer seu loop for:
Um pouco mais sensato / legível seria:
Mas isso é muito complexo, você só precisa de um espaço lá:
Sua
$line
variável não contém novas linhas. Ele contém instâncias de\
seguido porn
. Você pode ver isso claramente com:A substituição está substituindo aqueles por espaços, o que é suficiente para trabalhar em loops:
Demo:
fonte
cr
você pode usar$'\n'
.Você também pode primeiro converter a variável em uma matriz e iterar sobre isso.
Isso é útil apenas se você não quiser mexer com o
IFS
e também tiver problemas com oread
comando, pois pode acontecer, se você chamar outro script dentro do loop para que esse script possa esvaziar seu buffer de leitura antes de retornar, como aconteceu comigo .fonte