De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.
Colaboração: Julio Cezar Neves
Data de Publicação: 14 de agosto de 2019
O bash 4.0, nos trouxe uma novidade: o comando intrínseco (built-in) mapfile
, cuja finalidade é ler linhas da entrada primária (stdin) para dentro de um vetor indexado, sem fazer loop ou substituição de comando. Sua sintaxe é a seguinte:
mapfile [OPCS] [VETOR]
Onde os dados recebidos pela entrada primária irão para o vetor VETOR
. Caso ele não seja especificado, a variável do sistema, MAPFILE
, se incumbirá de receber esses dados.
As principais opções OPCS
são:
Opção | Efeito |
---|---|
-n QTD |
Copia, no máximo, QTD linhas |
-O ORIGEM |
Usa ORIGEM como o menor índice de VETOR |
-s QTD |
Descarta as primeiras QTD linhas |
-c QTD |
A cada QTD linhas lidas executa o que for especificado pela opção -c |
-C COD |
Executa o código Shell especificado em COD . O índice de VETOR é adicionado ao final |
Existem algumas formas de você copiar um arquivo para um vetor:
$ Vetor=($(cat Arquivo)) # 1? parênteses para gerar vetor $ read -a Vetor <<< $(cat Arquivo) $ mapfile Vetor < Arquivo
Mas o que importa aqui é o tempo, então faça:
$ seq 1000000 > Arquivo
e em seguida faa os seguintes testes:
$ time Vetor=( $(cat Arquivo)) $ time read -a Vetor <<< $(cat Arquivo) $ time mapfile Vetor < Arquivo
Você verá que a solução com o mapfile
é pelo menos 10 vezes mais rápida que as outras. Então vamos brincar com o mapfile
. Crie esse arquivo:
$ cat frutas abacate maçã morango pera tangerina uva $ mapfile vet < frutas $ echo ${vet[@]} # Lista todos os elementos de vetor vet abacate maçã morango pera tangerina uva
Vejamos como funcionam as suas principais opções:
$ mapfile -n3 vet < frutas # Para ler somente três linhas $ echo ${vet[@]} # Exibe os dados abacate maçã morango $ echo ${!vet[@]} # Exibe os índices 0 1 2 $ unset vet # "Mata" o vetor $ mapfile vet < frutas # Começando de novo $ echo ${vet[@]} $ echo ${!vet[@]} 0 1 2 3 4 5 $ mapfile -O 6 vet < frutas # Menor índice será o que já tinha mais 1 $ echo ${vet[@]} abacate maçã morango pera tangerina uva abacate maçã morango pera tangerina uva $ echo ${!vet[@]} 0 1 2 3 4 5 6 7 8 9 10 11 $ unset vet $ mapfile -s 3 vet < frutas # Despreza três linhas iniciais de frutas $ echo ${vet[@]} pera tangerina uva $ echo ${!vet[@]} 0 1 2 $ mapfile -c1 -C "echo -n carreguei o índice" < frutas carreguei o índice 0 abacate carreguei o índice 1 maçã carreguei o índice 2 morango carreguei o índice 3 pera carreguei o índice 4 tangerina carreguei o índice 5 uva
O mesmo resultado seria obtido se fizesse:
$ mapfile -c1 -C "printf 'carreguei o índice %d %s'" < frutas
carreguei o índice 0 abacate
carreguei o índice 1 maçã
carreguei o índice 2 morango
carreguei o índice 3 pera
carreguei o índice 4 tangerina
carreguei o índice 5 uva
No entanto, poderíamos desprezar os índices, que são automaticamente lançados para a saída, se não especificarmos a máscara do printf
para recebê-los (no caso %d
e %s
), fazendo uma barra de progresso rústica usando essa técnica. Vejamos:
$ mapfile -c1 -C "printf '#'" < frutas
######$
Nesses últimos exemplos, não especificamos o nome do vetor. Assim sendo, o Bash mandou todos os dados para MAPFILE
. Veja:
$ echo ${MAPFILE[@]}
abacate maçã morango pera tangerina uva
Isto é, foi lançado um jogo-da-velha (#) para cada elemento carregado no vetor. Isso é muito legal, mas se a quantidade de elementos for muito grande, a qualidade da apresentação será prejudicada. Para resolver isso, basta incrementar o valor da opção -c
. Observe também que o prompt ficou colado na saída, sem saltar linha. Para resolver isso, o melhor é colocar um echo
puro no final da linha. Vamos ver como carregar um vetor com 800.000 elementos:
$ printf '%s\n' {0..800000} | mapfile -c25000 -C 'printf "#"'; echo
################################
Como estamos gerando um vetor com 800.000 elementos, escrevendo um #
a cada 25.000 elementos conseguiremos entender o papel de barra de progresso.
As inscrições para o curso Programação Shell Linux com o Professor Julio Neves estão abertas!
This policy contains information about your privacy. By posting, you are declaring that you understand this policy:
This policy is subject to change at any time and without notice.
These terms and conditions contain rules about posting comments. By submitting a comment, you are declaring that you agree with these rules:
Failure to comply with these rules may result in being banned from submitting further comments.
These terms and conditions are subject to change at any time and without notice.
Comentários