você está aqui: Home  → Colunistas  →  Cantinho do Shell

 

Here Strings

Por Julio Cezar Neves

Data de Publicação: 22 de Janeiro de 2007

Primeiro um programador com complexo de inferioridade criou o redirecionamento de entrada e representou-o com um sinal de menor (<) para representar seus sentimentos. Em seguida, outro sentindo-se pior ainda, criou o here document representando-o por dois sinais de menor (<<) porque sua fossa era maior. O terceiro, pensou: "estes dois não sabem o que é estar por baixo"... Então criou o here strings representado por três sinais de menor (<<<).

Brincadeiras a parte, o here strings é utilíssimo e, não sei porque, é um perfeito desconhecido. Na pouquíssima literatura que sobre o tema, nota-se que o here strings é freqüentemente citado como uma variante do here document, com a qual discordo pois sua aplicabilidade é totalmente diferente daquela.

Sua sintaxe é simples:

$ comando <<< $cadeia

Onde cadeia é expandida e alimenta a entrada primária (stdin) de comando.

Como sempre, vamos direto aos exemplos dos dois usos mais comuns para que vocês próprios tirem suas conclusões.

Uso #1

Substituindo a famigerada construção echo "cadeia" | comando, que força um fork, criando um subshell e onerando o tempo de execução. Vejamos alguns exemplos:

$ a="1 2 3"
$ cut -f 2 -d ' ' <<< $a # normalmente faz-se: echo $a | cut -f 2 -d ' '
2
$ echo $NomeArq
Meus Documentos
$ tr "A-Z " "a-z_" <<< $NomeArq  Substituindo o echo ... | tr ...
meus_documentos
$ bc <<<"3 * 2"
6
$ bc <<<"scale = 4; 22 / 7"
3.1428

Para mostrar a melhoria no desempenho, vamos fazer um loop de 500 vezes usando o exemplo dados para o comando tr:

$ time for ((i=1; i<= 500; i++)); { tr "A-Z " "a-z_" <<< $NomeArq >/dev/null; }

real    0m3.508s
user    0m2.400s
sys     0m1.012s
$ time for ((i=1; i<= 500; i++)); { echo $NomeArq | tr "A-Z " "a-z_" >/dev/null; }

real    0m4.144s
user    0m2.684s
sys     0m1.392s

Veja agora esta seqüência de comandos com medidas de tempo:

$ time for ((i=1;i<=100;i++)); { who | cat > /dev/null; }

real    0m1.435s
user    0m1.000s
sys     0m0.380s
$ time for ((i=1;i<=100;i++)); { cat <(who) > /dev/null; }

real    0m1.552s
user    0m1.052s
sys     0m0.448s
$ time for ((i=1;i<=100;i++)); { cat <<< $(who) > /dev/null; }

real    0m1.514s
user    0m1.056s
sys     0m0.412s

Observando este quadro você verá que no primeiro usamos a forma convencional, no segundo usamos um named pipe temporário para executar uma substituição de processos e no terceiro usamos here string. Notará também que ao contrário do exemplo anterior, aqui o uso de here string não foi o mais veloz. Mas repare bem que neste último caso o comando who está sendo executado em um subshell e isso onerou o processo como um todo.

Vejamos uma forma rápida de inserir uma linha como cabeçalho de um arquivo:

$ cat num
1       2
3       4
5       6
7       8
9       10
$ cat - num <<< "Impares Pares"
Impares Pares
1       2
3       4
5       6
7       8
9       10

Uso #2

Outra forma legal de usar o here string é casando-o com um comando read, não perdendo de vista o que aprendemos sobre IFS (veja mais sobre está variável no Papo de Botequim). O comando cat com as opções -vet mostra o <ENTER> como $, o <TAB> como ^I e os outros caracteres de controle com a notação ^L onde L é uma letra qualquer. Vejamos então o conteúdo de uma variável e depois vamos ler cada um de seus campos:

Também podemos ler direto para um vetor (array) veja:

$ echo $Frutas
Pera:Uva:Maçã
$ IFS=:
$ echo $Frutas
Pera Uva Maçã        # Sem as aspas o shell mostra o IFS como branco
$ echo "$Frutas"  
Pera:Uva:Maçã        # Ahhh, agora sim!
$ read -a aFrutas <<< "$Frutas"  # A opção -a do read, lê para um vetor
$ for i in 0 1 2
> do
>     echo ${aFrutas[$i]}        # Imprimindo cada elemento do vetor
> done
Pera
Uva
Maçã

Bem , por enquanto é só! Mas se vocês descobrirem algo de novo no uso de here strings, façam o favor de nos enviar para tornar o Cantinho um cantão cheio de dicas de bash :)

Se você quer um livro livre e online vá a www.julioneves.com

Error: No site found with the domain 's2.dicas-l.com.br' (Learn more)