Iterando sobre Cadeia de Várias Linhas Armazenada na Variável

17

Eu li que é ruim escrever coisas como for line in $(command): a maneira correta parece ser:

command | while IFS= read -r line; do echo $line; done

Isso funciona muito bem. Mas e se o que eu quero repetir for o conteúdo de uma variável , não o resultado direto de um comando?

Por exemplo, imagine que você crie o seguinte arquivo quickfox:

The quick brown
foxjumps\ over -
the
lazy ,
dog.

Eu gostaria de poder fazer algo assim:

# This is just for the example,
# I could of course stream the contents to `read`
variable=$(cat quickfox);
while IFS= read -r line < $variable; do echo $line; done; # this is incorrect
Sheljohn
fonte

Respostas:

19

Em shells modernos como bash e zsh, você tem um redirecionador `<<< 'muito útil que aceita uma string como entrada. Então você faria

while IFS= read -r line ; do echo $line; done <<< "$variable"

Caso contrário, você sempre pode fazer

echo "$variable" | while IFS= read -r line ; do echo $line; done
lgeorget
fonte
Desculpe, eu deveria ter pensado em ecoar o conteúdo, é claro. Mas obrigado pela resposta rápida de qualquer maneira!
Sheljohn
11
você precisa citar duas vezes $variablequando usá-lo, caso contrário, o whileloop receberá apenas uma linha de entrada. Ver, por exemplo, a diferença na produção entre echo $variablevs echo "$variable"ou cat <<< $variablevs cat <<< "$variable".
cas
@cas Na verdade, depende do que está dentro da variável $. No caso apresentado pelo OP ("variável = $ (cat quickfox)"), ele funciona sem as aspas adicionais. Mas para o caso geral, você está certo. Eu edito minha resposta. Obrigado.
Lgeorget
A variable=$(cat quickfox)própria pergunta do OP fornece um exemplo do que eu estava falando. Usar isso $variableentre aspas duplas inclui as novas linhas; usá-lo sem que as novas linhas sejam convertidas em espaços pelo shell. Se você está lendo e processando linha por linha, isso faz uma enorme diferença - no primeiro você tem várias linhas de entrada, no segundo você tem apenas uma linha de entrada. Os dados de entrada são superficialmente semelhantes, mas, na prática, completamente diferentes nesses dois casos.
11556
por exemplo: com esses dados de entrada, cat <<< "$variable" | wc -lretorna 5. cat <<< $variable | wc -lretorna 1. Se você deseja / precisa preservar espaços em branco (incluindo novas linhas, guias, espaços únicos ou múltiplos) em uma variável, DEVE citar duas vezes a variável ao usá-la, caso contrário todos eles serão transformados em um único espaço entre cada "palavra".
11556