Eu tenho um comando retornando várias linhas. Para processamento adicional, eu preciso processar cada linha dessas linhas.
Meu código atual funciona modificando o IFS ( Internal Field Separator ):
ROWS=$(some command returning multiple lines)
O=$IFS #save original IFS
IFS=$(echo -en "\n\b") # set IFS to linebreak
for ROW in ${ROWS[@]}
do
echo "$ROW"
done
IFS=$O #restore old IFS
Gostaria de saber, existe uma maneira melhor de acessar as linhas únicas da saída de várias linhas, uma sem modificar o IFS? Especialmente a legibilidade do meu script fica ruim ao modificar o IFS.
Atualização: Tenho problemas para obter respostas, por exemplo, a da choroba:
while IFS= read -r line ; do
let var+=line #line 42
done << $(sqlite3 -list -nullvalue NULL -separator ',' /var/log/asterisk/master.db "${QUERY}")
echo "$var" # line 44
me dá
./bla.sh: row 44: Warning: here-document at line 43 delimited by end-of-file (wanted `$(sqlite3 -list -nullvalue NULL -separator , /var/log/asterisk/master.db ${QUERY})')
./bla.sh: row 42: let: echo "": syntax error: invalid arithmetic operator. (error causing character is \"""\").
Alguém pode me ajudar com isso? Obrigado!
bash
shell
command
command-substitution
stefan.at.wpf
fonte
fonte
< <(some command returning multiple lines)
, mas não é isso que você está fazendo.Respostas:
Que tal
read
em umwhile
loop?Tenha cuidado, porém, o pipe é executado em uma subshell, o que significa que você não pode alterar valores de variáveis para o restante do script. Se você precisar de algo para sobreviver a partir do loop while, poderá usar a substituição de processos do bash:
fonte
bash
, mas vale a pena notar que o escopo de subconjuntos de variáveis é apenas um problemabash
,zsh
pois fazer o mesmo não teria esse problema.Definir
IFS
apenas uma nova linha não é suficiente. (Por que você também está dividindo caracteres de backspace, a propósito?)No seu código,
${ROWS[@]}
(que é uma maneira estranha de escrever$ROWS
-ROWS
não é uma matriz) não é citado duas vezes. (Se estivesse entre aspas duplas, você obteria uma única string, já queROWS
não é uma matriz.) Portanto, o shell divide o valor da variável em campos em cadaIFS
caractere e depois trata cada campo como um padrão glob. Por exemplo, se uma das linhas impressas pelo comando contiver um caractere único*
, isso será substituído pelos nomes dos arquivos no diretório atual.Você pode desativar o globbing com
set -f
. Na maioria dos casos em que você define oIFS
uso do recurso de divisão de campo do shell, também precisa desativar o globbing. Coloque-o novamente comset +f
.O idioma confiável para ler a linha de saída de um comando por linha é
while IFS= read -r
.Observe que a maioria dos shells executa cada comando de um pipeline em um subshell separado. Portanto, se você precisar definir variáveis e usá-las após o loop, agrupe esses comandos em um grupo junto com o loop. (Ksh e zsh são as exceções, eles executam o último comando de um pipeline no shell pai.)
fonte
Você está misturando a sintaxe aqui-documento e aqui-string na sua pergunta de atualização.
Use aqui o documento:
Ou aqui-string:
fonte