Sobre a solução OP:
Uma solução que funciona em todos os shells (razoáveis) com os dois itens resolvidos é esta:
#!/bin/bash
nl="
"
read_heredoc(){
var=""
while IFS="$nl" read -r line; do
var="$var$line$nl"
done
}
read_heredoc <<'HEREDOC'
_ _ _
| | | (_)
_ __ ___ _ _ _ __ | | __ _ ___ ___ ___ _ __ | |_ _ __ ___
| '_ ' _ \| | | | '_ \| |/ _' |/ __/ _ \/ _ \| '_ \| | | '_ \ / _ \
| | | | | | |_| | |_) | | (_| | (_| __/ (_) | | | | | | | | | __/
|_| |_| |_|\__, | .__/|_|\__,_|\___\___|\___/|_| |_|_|_|_| |_|\___|
__/ | |
|___/|_|
HEREDOC
read_heredoc2_result="$str"
printf '%s' "${read_heredoc2_result}"
Uma solução para a pergunta original.
Uma solução que funciona desde o bash 2.04 (e recente zsh, lksh, mksh).
Veja abaixo uma versão mais portátil (POSIX).
#!/bin/bash
read_heredoc() {
IFS='' read -d '' -r var <<'HEREDOC'
_ _ _
| | | (_)
_ __ ___ _ _ _ __ | | __ _ ___ ___ ___ _ __ | |_ _ __ ___
| '_ ' _ \| | | | '_ \| |/ _' |/ __/ _ \/ _ \| '_ \| | | '_ \ / _ \
| | | | | | |_| | |_) | | (_| | (_| __/ (_) | | | | | | | | | __/
|_| |_| |_|\__, | .__/|_|\__,_|\___\___|\___/|_| |_|_|_|_| |_|\___|
__/ | |
|___/|_|
HEREDOC
}
read_heredoc
echo "$var"
O comando principal
IFS='' read -d '' -r var <<'HEREDOC'
funciona da seguinte forma:
- A palavra
HEREDOC
é (única) citada para evitar qualquer expansão do texto que se segue.
- O conteúdo "here doc" é exibido no stdin com
<<
.
- A opção
-d ''
força read
a fazer slurp de todo o conteúdo do "here doc".
- A opção
-r
evita a interpretação de caracteres citados com barra invertida.
- O comando principal é semelhante a
read var
.
- E o último detalhe é
IFS=''
, o que evitará que a leitura remova os caracteres iniciais ou finais na guia padrão do IFS: espaço nova linha
Em ksh, o valor nulo para a opção -d ''
não funciona.
Como solução alternativa, se o texto não tiver "retorno de carro", um -d $'\r'
funciona (se um $'\r'
for adicionado ao final de cada linha, é claro).
Um requisito adicionado (em comentários) é gerar uma solução compatível com POSIX.
POSIX
Estendendo a ideia para executá-lo apenas com opções POSIX.
Isso significa principalmente que não há -d
para read
. Isso força uma leitura para cada linha.
Isso, por sua vez, força a necessidade de capturar uma linha de cada vez.
Então, para construir o var
, uma linha nova deve ser adicionada (à medida que a leitura é removida).
#!/bin/sh
nl='
'
read_heredoc() {
unset var
while IFS="$nl" read -r line; do
var="$var$line$nl"
done <<\HEREDOC
_ _ _
| | | (_)
_ __ ___ _ _ _ __ | | __ _ ___ ___ ___ _ __ | |_ _ __ ___
| '_ ' _ \| | | | '_ \| |/ _' |/ __/ _ \/ _ \| '_ \| | | '_ \ / _ \
| | | | | | |_| | |_) | | (_| | (_| __/ (_) | | | | | | | | | __/
|_| |_| |_|\__, | .__/|_|\__,_|\___\___|\___/|_| |_|_|_|_| |_|\___|
__/ | |
|___/|_|
HEREDOC
}
read_heredoc
printf '%s' "$var"
Isso funciona (e foi testado) em todos os shells razoáveis.