O problema é que você não está citando a variável $ENV
. Conforme explicado em man bash
:
Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, ', \, and, when history expansion is enabled, !. The characters $ and ' retain their special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: $, ', ", \, or .
Portanto, incluir uma sequência como \n
nas aspas duplas preserva seu significado. É por isso que, quando não é cotado, \n
é apenas um% normaln
:
$ printf \n
n$
Enquanto, quando citado:
$ printf "\n"
$
Uma variável sem nome no bash invoca o operador split + glob. Isso significa que a variável é dividida em espaço em branco (ou qualquer que seja a variável especial $IFS
definida) e cada palavra resultante é usada como glob (expandirá para corresponder a qualquer nome de arquivo correspondente). Seu problema é com a parte "dividida" disso.
Para ilustrar, vamos pegar uma variável multilinha mais simples:
$ var=$(printf "foo\nbar\n")
Agora, usando o recurso de depuração set -x
do shell, você pode ver exatamente o que está acontecendo:
$ echo $var
+ echo foo bar
foo bar
$ echo "$var"
+ echo 'foo
bar'
foo
bar
Como você pode ver acima, echo $var
(sem aspas) apresenta $var
para dividir + glob. Isso resulta em duas sequências separadas, foo
e bar
. A nova linha foi comida pela divisão split + glob. Quando a variável foi citada, não foi submetida a split + glob, a nova linha foi mantida e, por ser citada, também é interpretada corretamente e impressa.
O próximo problema é que printf
não é como echo
. Ele não imprime apenas qualquer coisa que você der, ele espera uma string de formato. Por exemplo, printf "color:%s" "green"
imprimirá color:green
porque o %s
será substituído por green
.
Ele também ignora qualquer entrada que não possa caber na string de formato que foi fornecida. Portanto, se você executar printf foo bar
, printf
tratará foo
como sua string de formato e bar
como a variável que deve formatar com ela. Como não há %s
ou equivalente a ser substituído por bar
, bar
é ignorado e foo
é impresso sozinho:
$ printf $var
+ printf foo bar
foo
Foi o que aconteceu quando você executou printf $ENV_BEFORE
. Como a variável não foi citada, a divisão glob substituiu efetivamente as novas linhas por espaços, e printf
apenas imprimiu a primeira "palavra" que viu.
Para fazer isso corretamente, use strings de formato e sempre cite suas variáveis:
printf '%s\n' "$ENV_BEFORE"