O que é um here string?

Um here string nada mais é do que uma maneira de transformar uma string na entrada padrão (stdin) de um programa. Normalmente utilizamos essa técnica pegando a string contida em uma variável.

A sintaxe, pegando de uma variável, é a seguinte:

COMMAND <<< "$VAR"

Onde o conteúdo variável $VAR será colocado na entrada padrão do COMMAND.

Usar a técnica do here string evita o uso de estruturas como:

# uso desnecessário do echo
echo "$var" | grep padrao

Podemos obter o mesmo resultado usando a sintaxe do here string:

grep padrao <<< "$var"

Na minha opinião, o código fica mais limpo e legível desta forma. Além disso, também temos um ganho de performance.

A explicação para isso está num trecho do manual do bash que fala de Pipelines (tradução livre):

Cada comando em um pipeline é executado em seu próprio subshell, o que é um processo separado (…)

Ou seja, a cada pipe um subshell é inicializado, e isso gera um custo de performance. Principalmente se você estiver fazendo isso dentro de um loop com dezenas/centenas de iterações.

Espero que estes dois fatores (1. código limpo, 2. performance) sejam motivos suficientes para você começar a usar o here string a partir de agora.

Quando não usar here strings

Conforme podemos ver no próprio manual do bash (tradução livre):

O resultado é enviado à entrada padrão do comando, como uma única string e com uma nova linha adicionada ao final

Portanto, em casos onde esse caractere de nova linha não é desejado, não podemos usar o here string. Estes casos são bem raros, mas acontecem.

Eu me deparei com esse problema quando estava trabalhando numa aplicação onde eu precisava calcular o checksum MD5 dos 8 primeiros bytes de um arquivo. Vou ilustrar o problema através do exemplo a seguir:

$ cat texto.txt
conteudo do arquivo

$ head -c8 texto.txt | md5sum
b59853db2f3ef8f156a72e38c30ba7d2  -
$ 
$ # armazenando o conteúdo em uma variavel
$ variavel=$(head -c8 texto.txt)
$ md5sum <<< "$variavel"
746378123fbe2cbca33ed5d88f35c5bb  -
$ # ué! era pra ser igual ao md5 lá de cima!
$ 
$ # vejamos com o 'echo -n' (sem nova linha no final):
$ echo -n "$variavel" | md5sum
b59853db2f3ef8f156a72e38c30ba7d2  -
$ # agora sim! o checksum é igual! :)

Conforme podemos ver, nas raríssimas situações onde o caracter de nova linha no final da string pode alterar o resultado desejado, o uso de here strings não resolve.

Cuidado com o exagero

Legal, você aprendeu que usando here strings você tem um ganho de performance, mas também não precisa ficar fissurado com isso e usar here strings em toda e qualquer oportunidade.

Entenda que a função dessa técnica é colocar uma string no arquivo de entrada padrão de um comando.

Eu já vi um caso onde a pessoa usou comando <<< $(< arquivo). Ou seja, através do redirecionamento no $() ele colocou o conteúdo de um arquivo numa string para logo em seguida mandar essa string para a entrada padrão do comando. Neste caso bastava usar simplesmente comando < arquivo.

Fontes