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
.