|
From: | Julio C. Neves |
Subject: | Re: [shell-script] Re: Operação Bitwise em Bash |
Date: | Mon, 21 Oct 2019 13:43:58 -0300 |
Já tinha mandado a décima edição deste livro para a editora quando o Alfredo Casanova, colega da lista shell-script do Yahoo Groups, mandou a seguinte dica para a nossa lista:
“Só compartilhando uma funçãozinha que fiz aqui para desenhar caixas de mensagem (só funciona para mensagens com uma linha. Se alguém quiser alterar, fique à vontade)”
E nos brindou com esse código:
function DrawBox
{
string="$*";
tamanho=${#string}
tput setaf 4; printf "\e(0\x6c\e(B"
for i in $(seq $tamanho)
do printf "\e(0\x71\e(B"
done
printf "\e(0\x6b\e(B\n"; tput sgr0;
tput setaf 4; printf "\e(0\x78\e(B"
tput setaf 1; tput bold; echo -n $string; tput sgr0
tput setaf 4; printf "\e(0\x78\e(B\n"; tput sgr0;
tput setaf 4; printf "\e(0\x6d\e(B"
for i in $(seq $tamanho)
do printf "\e(0\x71\e(B"
done
printf "\e(0\x6a\e(B\n"; tput sgr0;
}
Seu uso seria da seguinte forma:
$ DrawBox Qualquer frase que caiba no terminal
Qualquer frase que caiba no terminal |
Só que essa caixa é azul (tput setaf 4) e as letras são vermelhas, com ênfase (tput setaf 1; tput bold).
Mas observe a tabela a seguir. Ela explica os códigos gerados por esse monte de printf estranho:
O printf |
Produz |
\e(0\x6c\e(B |
┌ |
\e(0\x71\e(B |
– |
\e(0\x6b\e(B |
┐ |
\e(0\x78\e(B |
│ |
\e(0\x6d\e(B |
└ |
\e(0\x6a\e(B |
┘ |
Como eu tinha acabado de escrever os exemplos que vimos antes e ainda estava com eles na cabeça, sugeri que o for que ele usou para fazer as linhas horizontais fosse trocado; assim, substituiríamos:
for i in $(seq $tamanho)
do printf "\e(0\x71\e(B"
done
Por:
printf -v linha "%${tamanho}s" ' '
printf -v traco "\e(0\x71\e(B"
echo -n ${linha// /$traco}
Tudo Shell puro, pois o for, o printf e o echo são builtins, mas como o printf dentro do for seria executado tantas vezes quantos traços horizontais houvessem, imaginei que a minha solução fosse um pouco mais veloz e lhe pedi para testar os tempos de execução, não sem antes apostar um chope. Ele criou dois scripts, um que executava mil vezes a função que ele havia proposto e outro que fazia o mesmo com a minha solução. Não vou dizer qual foi a forma mais veloz, porém adianto que o Alfredo está me devendo um chope... ;)
O código otimizado ficaria assim:
function DrawBox
{
string="$*";
tamanho=${#string}
tput setaf 4; printf "\e(0\x6c\e(B"
printf -v linha "%${tamanho}s" ' '
printf -v traco "\e(0\x71\e(B"
echo -n ${linha// /$traco}
printf "\e(0\x6b\e(B\n"; tput sgr0;
tput setaf 4; printf "\e(0\x78\e(B"
tput setaf 1; tput bold; echo -n $string; tput sgr0
tput setaf 4; printf "\e(0\x78\e(B\n"; tput sgr0;
tput setaf 4; printf "\e(0\x6d\e(B"
printf -v linha "%${tamanho}s" ' '
printf -v traco "\e(0\x71\e(B"
echo -n ${linha// /$traco}
printf "\e(0\x6a\e(B\n"; tput sgr0;
}
Então agora, voltando aos nossos exemplos de passar uma linha por todo o terminal, posso sugerir uma outra (e mais bonita) solução:
Para passar uma linha por todo o terminal (Dica 3)
printf -v linha "%$(tput cols)s" ' '
printf -v traco "\e(0\x71\e(B"
echo ${linha// /$traco}
Creio que quando resolvi explicar o printf através de exemplos acertei em cheio, pois não saberia como enumerar tantas regrinhas sem tornar a leitura enfadonha.
=======================================================================
Agora o material sobre o mapfile, que te prometi (repare que ele não menciona a opção que vc usou, em virtude dela só ter sido incrementada no bash 4.4):
Lendo um arquivo para um vetor
Ainda falando do bash
4.0, eis que ele surge com uma outra
novidade: o comando intrínseco (builtin)
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 |
EPA! Isso deve ser muito rápido!
E é. Faça os testes e comprove! Veja só como ele funciona:
$ cat frutas Não confunda o arquivo com o vetor que usamos
abacate
maçã
morango
pera
tangerina
uva
$ mapfile vet < frutas Mandando frutas para vetor vet
$ echo ${vet[@]} Listando todos os elementos de vet
abacate maçã morango pera tangerina uva
Obteríamos resultado idêntico se fizéssemos:
$ vet=($(cat frutas))
Porém, isso seria mais lento porque a substituição de comando é executada em um subshell. Uma outra forma de fazer isso que logo vem à cabeça é ler o arquivo com a opção -a do comando read. Vamos ver como seria o comportamento disso:
$ read -a vet < frutas
$ echo ${vet[@]}
abacate
Como deu para perceber, foi lido somente o primeiro registro de frutas porque esse formato de read precisa receber todos os dados que serão lidos para o vetor vet. Para consertar isso poderíamos fazer:
$ read -a vet <<< $(cat frutas)
$ echo ${vet[@]}
abacate maçã morango pera tangerina uva
Mas aí a performance será pior até do que a anterior, pois também usa substituição de comandos e ainda por cima usa a instrução cat, que não é builtin.
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[@]}
abacate maçã morango pera tangerina uva
$ 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). Veja:
$ mapfile -c1 -C"printf 'Carreguei o índice'" < frutas
Carreguei o índiceCarreguei o índiceCarreguei o índiceCarreguei o índiceCarreguei o índiceCarreguei o índice
Epa, isso me deu uma ideia! Posso simular uma barra de progresso rústica usando essa técnica. Vejamos:
$ mapfile -c1 -C"printf '#'" < frutas
######$
Nesses últimos exemplos, por não termos especificado o nome do vetor, o Bash mandou todos os dados para um vetor do sistema chamado 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 duzentos elementos:
$ printf '%s\n' {1..200} | mapfile -c20 -C 'printf "#"'; echo
##########
=============================================================================Julio, confirmei aqui e, de fato, o readarray é um alias pro mapfile$ readarray --help
readarray: readarray [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
Read lines from a file into an array variable.
A synonym for `mapfile'.On Sat, Oct 19, 2019 at 12:03 AM 'Julio C. Neves' address@hidden [shell-script] <address@hidden> wrote:Acho que o readarray é um aliás do mapfile. Qdo ligar o computador, te mando o que escrevi sobre esse cmd.Bom fim de semanaEm sex, 18 de out de 2019 12:08, Alfredo Casanova address@hidden [shell-script] <address@hidden> escreveu:Eu li sobre a readarray essa semana, Júlio. Mas como fiz o script pra solucionar uma busca que precisamos aqui no trabalho e vai rodar num ambiente que eu controlo, não vi grandes problemas..
O redirect pro stderr eu vou colocar mesmo :)
Valeu!On Fri, Oct 18, 2019 at 11:42 AM 'Julio C. Neves' address@hidden [shell-script] <address@hidden> wrote:Troque:por:Eu não usaria o readarray com a opção -d pq ele só foi implementada na última versão do bash (4.4) o que a torna incompatível com diversos ambientes.Abraços,Julio» Não tem tempo para fazer um curso presencial?» Na sua cidade não tem nenhum bom curso de Linux?» Em outubro abriremos uma semana de inscrições» para uma nova turma. Veja mais detalhes em:Também damos treinamento em sua empresaem qualquer cidade, com certificado e nota fiscal.Em qui, 17 de out de 2019 às 10:50, Alfredo Casanova address@hidden [shell-script] <address@hidden> escreveu:Terminei o código (não sei se tá certo pq networking não é a minha MESMO, tive q pegar ajuda com vários amigos)Nos testes que fiz, tá funcionando.
Se alguém quiser dar uma olhada (e corrigir, caso encontre erros), segue:On Thu, Oct 17, 2019 at 10:18 AM 'Julio C. Neves' address@hidden [shell-script] <address@hidden> wrote:Arkanon!!!!!! Que bom tê-lo de volta na lista!!! Nos conte como anda o LSD, pois tem tudo a ver com Shell.A ideia era te cumprimentar, mas só para não sair do escopo da lista e já que vc falou em bc e [io]base, vou mostrar uma coisa, que por não ser muito conhecida, alguns pensam ser um erro do utilitário:$ bc <<< "ibase=8; obase=16; 10+10"
12
$ bc <<< "obase=8; ibase=16; 10+10"
40Isso ocorreu pq na 1a linha primeiro declaramos a input base como 8 e qdo declaramos a 2a como 16 ele já entendeu que esse 16 era na base 8, ou seja 14.Conclusão: qdo for declarar a duas bases, declare 1o a de saída.Abraços,Julio» Não tem tempo para fazer um curso presencial?» Na sua cidade não tem nenhum bom curso de Linux?» Em outubro abriremos uma semana de inscrições» para uma nova turma. Veja mais detalhes em:Também damos treinamento em sua empresaem qualquer cidade, com certificado e nota fiscal.Em qua, 16 de out de 2019 às 19:52, Arkanon address@hidden [shell-script] <address@hidden> escreveu:O bash considera números iniciando com 0 como na base octal:$ echo $(( 01010 & 01010 ))
520Se não começar com 0, considerará na base decimal:$ echo $(( 1010 & 1010 ))
1010Você pode indicar a base explicitamente:$ echo $(( 8#1010 & 8#1010 ))
520$ echo $(( 10#01010 & 10#01010 ))
1010Portanto, se quer que seja considerada a base binária, indique-a:$ echo $(( 2#00001010 & 2#00001010 ))
10$ echo $(( 2#1010 & 2#1010 ))
10Aliás, a base hexadecimal também tem sua sintaxe específica:$ echo $(( 0x01010 & 0x01010 ))
4112
$ echo $(( 16#01010 & 16#01010 ))
4112Observe que o resultado é dado na base decimal. Se quiser o resultado na mesma base de entrada, pode convertê-lo. Aqui tem algumas sugestões de procedimento:$ dec=844
$ printf '%x\n' $dec # para hexadecimal
34c
$ printf '%X\n' $dec
34C
$ printf '%o\n' $dec # para octal
1514
$ bc <<< "obase=2;$dec" # para binario
1101001100 $ dec=844$ bc <<< "obase=21;$dec" # para base 21 -> QUALQUER BASE
01 19 04Att,Em qua, 16 de out de 2019 às 19:25, Alfredo Casanova address@hidden [shell-script] <address@hidden> escreveu:Pelo visto ele está fazendo bitwise comparando 1.100 com 1.010.Como fugir disso?Em qua, 16 de out de 2019 19:07, Alfredo Casanova <address@hidden> escreveu:Galera, to fazendo um script aqui pra detectar se uma sub-rede menos abrangente está compreendida dentro de outra mais abrangente (exemplo: saber se a rede 10.100.100.128/25 está dentro da rede 10.100.100.0/24)E aí no meio das operacoes de bitwise me peguei com um erro que nao consigo explicar:$ echo $(( 11111111 & 11111111))
11111111
$ echo $(( 11111111 & 11111110))
11111110Essas duas operações estão com comportamento adequadoPorém:
$ echo $(( 00001010 & 00001010 ))
520
$ echo $(( 00001010 & 00001100 ))
512eu não faço ideia do q está acontecendo nesses casos.
Alguém ilumina?--[]'s
Alfredo Tristão Casanova .͘.
Linux User #228230
tel: +55 61 9655 9619
--(o_ @arkanon (Twitter) __o
//\ address@hidden _`\<,
V_/_ www.lsd.org.br (_)/(_)
-----------------------------------[]'s
Alfredo Tristão Casanova .͘.
Linux User #228230
tel: +55 61 9655 9619--[]'s
Alfredo Tristão Casanova .͘.
Linux User #228230
tel: +55 61 9655 9619--[]'s
Alfredo Tristão Casanova .͘.
Linux User #228230
tel: +55 61 9655 9619
[Prev in Thread] Current Thread [Next in Thread]
- Re: [shell-script] Re: Operação Bitwise em Bash, (continued)
- Re: [shell-script] Re: Operação Bitwise em Bash, Arkanon, 2019/10/16
- Re: [shell-script] Re: Operação Bitwise em Bash, Alfredo Casanova, 2019/10/16
- Re: [shell-script] Re: Operação Bitwise em Bash, Julio C. Neves, 2019/10/17
- Re: [shell-script] Re: Operação Bitwise em Bash, Alfredo Casanova, 2019/10/17
- Re: [shell-script] Re: Operação Bitwise em Bash, Thomaz de Oliveira dos Reis, 2019/10/17
- Re: [shell-script] Re: Operação Bitwise em Bash, Alfredo Casanova, 2019/10/17
- Re: [shell-script] Re: Operação Bitwise em Bash, Julio C. Neves, 2019/10/18
- Re: [shell-script] Re: Operação Bitwise em Bash, Alfredo Casanova, 2019/10/18
- Re: [shell-script] Re: Operação Bitwise em Bash, Julio C. Neves, 2019/10/18
- Re: [shell-script] Re: Operação Bitwise em Bash, Alfredo Casanova, 2019/10/21
- Re: [shell-script] Re: Operação Bitwise em Bash, Julio C. Neves <=
- Re: [shell-script] Re: Operação Bitwise em Bash, Alfredo Casanova, 2019/10/21
- Re: [shell-script] Re: Operação Bitwise em Bash, Arkanon, 2019/10/19
Re: [shell-script] Operação Bitwise em Bash, Julio C. Neves, 2019/10/17
- Re: [shell-script] Operação Bitwise em Bash, Alfredo Casanova, 2019/10/17
- Re: [shell-script] Operação Bitwise em Bash, Julio C. Neves, 2019/10/18
- Prev by Date: Re: [shell-script] Re: Operação Bitwise em Bash
- Next by Date: Re: [shell-script] Re: Operação Bitwise em Bash
- Previous by thread: Re: [shell-script] Re: Operação Bitwise em Bash
- Next by thread: Re: [shell-script] Re: Operação Bitwise em Bash
- Index(es):