Para processar a saída de uma linha de comando por linha ( explicação ):
jobs |
while IFS= read -r line; do
process "$line"
done
Se você já tiver os dados em uma variável:
printf %s "$foo" | …
printf %s "$foo" é quase idêntico a echo "$foo" , mas imprime $foo literalmente, enquanto echo "$foo" pode interpretar $foo como uma opção para o comando echo se começar com - e pode expandir a barra invertida seqüências em $foo em alguns shells.
Note que em alguns shells (ash, bash, pdksh, mas não em ksh ou zsh), o lado direito de um pipeline é executado em um processo separado, então qualquer variável que você definir no loop é perdida. Por exemplo, o seguinte script de contagem de linhas imprime 0 nesses shells:
n=0
printf %s "$foo" |
while IFS= read -r line; do
n=$(($n + 1))
done
echo $n
Uma solução alternativa é colocar o restante do script (ou pelo menos a parte que precisa do valor de $n do loop) em uma lista de comandos:
n=0
printf %s "$foo" | {
while IFS= read -r line; do
n=$(($n + 1))
done
echo $n
}
Se a ação nas linhas não vazias for boa o suficiente e a entrada não for grande, você poderá usar a divisão de palavras:
IFS='
'
set -f
for line in $(jobs); do
# process line
done
set +f
unset IFS
Explicação: configurar IFS para uma única nova linha faz a divisão de palavras ocorrer apenas em novas linhas (em oposição a qualquer caractere de espaço em branco na configuração padrão). set -f desativa a globulação (ou seja, expansão de caractere curinga), que, de outra forma, ocorreria com o resultado de uma substituição de comando $(jobs) ou uma variável substituta $foo . O loop for atua em todas as partes de $(jobs) , que são todas as linhas não vazias na saída do comando. Finalmente, restaure as configurações globbing e IFS .