Eu gostaria de processar uma string de várias linhas e iterar linha por linha, em um shell POSIX ( /bin/sh
) em uma plataforma BSD. O Bash não está incluído na distribuição BSD básica e tem uma licença GPL - então estou tentando fazê-lo funcionar universalmente /bin/sh
.
Eu encontrei uma solução usando um pipe, no entanto, no /bin/sh
shell regular, eles são processados em um processo separado, o que significa que o seguinte não funciona:
MULTILINE="`cat ${SOMEFILE}`"
SOMEVAR="original value"
echo "${MULTILINE}" | while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
echo "this is a single line: ${SINGLELINE}"
echo "SOMEVAR is now: ${SOMEVAR}"
done
echo "Final SOMEVAR is unchanged: ${SOMEVAR}"
No exemplo acima, ele realiza o que eu quero, exceto pelo fato de que as alterações em variáveis como ${SOMEVAR}
não são acessíveis fora do loop while.
Minha pergunta: como posso realizar algo como o acima sem essa restrição? Observe que muitas soluções exigem Bash, enquanto estou usando o POSIX-shell padrão /bin/sh
.
Você pode usar um documento aqui:
Dependendo da
sh
implementação, here-documents são implementados como um arquivo temporário excluído onde o shell armazenou a expansão da variável seguida por uma nova linha de antemão, ou um canal para o qual o shell alimenta a expansão da variável seguida por uma nova linha. Mas em ambos os casos, exceto no shell Bourne original (um shell que não está mais em uso atualmente e não é um shell compatível com POSIX), o comando que está sendo redirecionado não é executado em um subshell (como o POSIX exige).ou você pode usar split+glob:
Mas cuidado, ele pula linhas vazias.
Você leria diretamente do arquivo sem o pipeline. Isso evita a execução do
while
loop em um subshell, que permite que você veja o valor alterado de$SOMEVALUE
após o loop.Se você insistir em ter sua
$MULTILINE
variável, escreva isso em um arquivo e leia a partir daí:Também relacionado:
Uma resposta para a pergunta vinculada acima também sugere escrever seu programa de forma que todos os usos de
$SOMEVAR
ocorram no subshell no final do pipeline:Também possivelmente relacionado:
Outras questões que podem ser do seu interesse:
Funciona para mim :
e