shell-script-pt
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [shell-script] printf em um loop while só funcionou com eval


From: Paulo Bettega
Subject: Re: [shell-script] printf em um loop while só funcionou com eval
Date: Sun, 01 Feb 2015 12:21:59 -0200
User-agent: Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Thunderbird/31.4.0

Olá Julio, valeu as dicas. O operador ternário tem no Programação Shell Linux :)
Esse operador realmente não lembro de usar, e aí vai ficando esquecido.
O shell tem tantas maneiras de fazer a mesma coisa que na hora de escrever
acabo usando o trivial.

Abraços Paulo Bettega


On 31-01-2015 20:55, 'Julio C. Neves' address@hidden [shell-script] wrote:
Fala Paulo,
interessante essa discussão do printf... Mas como aparentemente vc já resolveu 
esse pepino, queria
te dar duas dicas:

A cada texto lido, vc compara com tabulação. Eu guardaria tudo num array ou até 
em uma variável e
para pegar o tamanho do maior usaria wc -L.
        -L, --max-line-length
               print the length of the longest line
Caso vc não queira fazer assim, useo operador ternário que é infinitamente mais 
veloz. Faça:
$ tabulacao=8
$ texto=fgergewhwthwrthw
$ tabulacao=$((tabulacao < ${#texto} ? ${#texto}+2 : $tabulacao)) # esse é o 
ternário
$ echo $tabulacao
18



Abcs,
Julio
*@juliobash**
Próximos cursos de Shell*
*Cidade        LocalPeríodo*
*Rio de JaneiroEDX <http://edx.srv.br/>09 a 13/03/15*
*São Paulo 4Linux 
<http://www.4linux.com.br/cursos/programacao-em-shell-script>23 a 27/03/15 *
Dou treinamento de /Shell/ em qualquer cidade.
Para mais detalhes, me mande um e-mail <mailto:address@hidden>.


Em 31 de janeiro de 2015 19:37, Paulo Bettega address@hidden
<mailto:address@hidden> [shell-script] <address@hidden
<mailto:address@hidden>> escreveu:

    Olá Ronaldo, valeu a lembrança do set -x, realmente não lembrei de 
verificar com o debug.

    Colei apenas as linhas referentes ao printf.
    set -x
    d1=4;d2=10;d3=5;m1=5;m2=3;m3=12;ano=2015
    while read linha; do printf '%20s%02d/%02d/%d\n' $linha
    done <<<"'Data: ' $d1 $m1 $ano
    'Outra Data: ' $d2 $m2 $ano
    'Mais uma data: ' $d3 $m3 $ano"
    + read linha
    + printf '%20s%02d/%02d/%d\n' ''\''Data:' \' 4 5 2015
                    'Data:00/04/5
                      201500/00/0
    + read linha
    + printf '%20s%02d/%02d/%d\n' ''\''Outra' Data: \' 10 3 2015
    -su: printf: Data:: invalid number
                    'Outra00/00/10
                         32015/00/0
    + read linha
    + printf '%20s%02d/%02d/%d\n' ''\''Mais' uma data: \' 5 12 2015
    -su: printf: uma: invalid number
    -su: printf: data:: invalid number
                     'Mais00/00/0
                         512/2015/0

    Parece que o shel adiciona alguns apóstrofos, e os apóstrofos que eu 
coloquei
    pra proteger o texto acho que são os que aparecem escapados.


    Com eval e o \n escapado dá pra ver que o shell monta a linha
    como eu imaginei sem o eval: printf '%20s%02d/%02d/%d\n' 'Data: ' 4 5 2015

    while read linha; do eval printf '%20s%02d/%02d/%d\\n' $linha
    done <<<"'Data: ' $d1 $m1 $ano
    'Outra Data: ' $d2 $m2 $ano
    'Mais uma data: ' $d3 $m3 $ano"
    + read linha
    + eval printf '%20s%02d/%02d/%d\\n' ''\''Data:' \' 4 5 2015
    ++ printf '%20s%02d/%02d/%d\n' 'Data: ' 4 5 2015
                    Data: 04/05/2015
    + read linha
    + eval printf '%20s%02d/%02d/%d\\n' ''\''Outra' Data: \' 10 3 2015
    ++ printf '%20s%02d/%02d/%d\n' 'Outra Data: ' 10 3 2015
              Outra Data: 10/03/2015
    + read linha
    + eval printf '%20s%02d/%02d/%d\\n' ''\''Mais' uma data: \' 5 12 2015
    ++ printf '%20s%02d/%02d/%d\n' 'Mais uma data: ' 5 12 2015
           Mais uma data: 05/12/2015


    Aqui vai um esboço do script. O número de linhas que serão impressas pode
    variar, por isso pensei em colocar o printf dentro do loop.
    Além disso o alinhamento do texto deve ser conforme a variável $texto mais 
longa.
    (aqui teve outro problema. As outras linhas ficavam dois caracteres 
desalinhadas
    com a linha mais longa. Somando dois na $tabulacao resolveu).
    Pensei nisso mais como um exercício, mas no fim das contas ficou bem mais
    complicado do que eu achei que ficaria.

    #!/bin/bash

    tabulacao=1
    datas=()
    while true; do
              read -p "Texto: " texto
              # Guarda o maior comprimento de $texto para usar
              # como alinhamento no printf.
              [ "${#texto}" -gt "$tabulacao" ] && tabulacao=$((${#texto}+2))
              [ "$texto" = 'fim' ] && break
              texto="$texto: "
              read -p "Dia: " dia
              read -p "Mês: " mes
              read -p "Ano: " ano
              datas=( "${datas[@]}" "'$texto' $dia $mes $ano" )
    done

    for i in $(seq ${#datas[*]}); do
              eval 'printf "%${tabulacao}s%02d/%02d/%d\n"' ${datas[$((i-1))]}
    done


    Abraços Paulo Bettega


    On 31-01-2015 11:39, Ronaldo Ferreira de Lima address@hidden 
<mailto:address@hidden>
    [shell-script] wrote:
      > É possível verificar o que aconteceu usando o "modo debug" set -x, o
      > grande problema foram os espaços "extras". Para evitar essas surpresas é
      > recomendável utilizar o método tradicional:
      >
      > printf '%20s: %02d/%02d/%d\n' "$str" $dia $mes $ano
      >
      > []'s
      > --
      > "Não manejo bem as palavras
      > Mas manipulo bem as strings."
      > ------------------------------
      > http://tecnoveneno.blogspot.com
      >


     > On Sat, Jan 31, 2015 at 02:49:55AM -0200, Paulo Bettega address@hidden
    <mailto:address@hidden> [shell-script] wrote:
     >  > Olá pessoal, tentei fazer esse loop, já que a linha do printf é 
sempre a mesma.
     >  > (Sei que nesse caso o loop é praticamente igual a escrever uma linha 
de
     >  > printf para cada linha do 'here strings', mas no futuro pretendo 
colocar
     >  > os dados num vetor).
     >  >
     >  > d1=4;d2=10;d3=5;m1=5;m2=3;m3=12;ano=2015
     >  > while read linha; do printf '%20s%02d/%02d/%d\n' $linha
     >  > done <<<"'Data: ' $d1 $m1 $ano
     >  > 'Outra Data: ' $d2 $m2 $ano
     >  > 'Mais uma data: ' $d3 $m3 $ano"
     >  >
     >  > A saída que eu queria era essa (talvez perca o alinhamento, os : são 
alinhados)
     >  > Data: 04/05/2015
     >  > Outra Data: 10/03/2015
     >  > Mais uma data: 05/12/2015
     >  >
     >  > mas o resultado foi esse
     >  > 'Data:00/04/5
     >  > 201500/00/0
     >  > bash: printf: Data:: invalid number
     >  > 'Outra00/00/10
     >  > 32015/00/0
     >  > bash: printf: uma: invalid number
     >  > bash: printf: data:: invalid number
     >  > 'Mais00/00/0
     >  > 512/2015/0
     >  >
     >  > Não entendi porque aconteceu isso, me pareceu tudo certo, pois o 
texto está
     >  > entre aspas simples, então o printf deveria reconhecer o texto todo 
como string %20s
     >  > e as três variáveis com a formatação da data %02d/%02d/%d
     >  >
     >  > Não sei porque, mas achei que o printf não estava recebendo a 
variável $linha como deveria,
     >  > então "chutei" um eval antes do printf, e o resultado foi animador:
     >  >
     >  > while read linha; do eval printf '%20s%02d/%02d/%d\n' $linha
     >  > done <<<"'Data: ' $d1 $m1 $ano
     >  > 'Outra Data: ' $d2 $m2 $ano
     >  > 'Mais uma data: ' $d3 $m3 $ano"
     >  > Data: 04/05/2015n Outra Data: 10/03/2015n Mais uma data: 05/12/2015n
     >  >
     >  > O resultado foi o que eu queria, apenas não quebrou a linha porque o 
\n
     >  > foi interpretado como "escapen", eu acho.
     >  > Então coloquei outro escape antes do \n e deu certo:
     >  >
     >  > while read linha; do eval printf '%20s%02d/%02d/%d\\n' $linha
     >  > done <<<"'Data: ' $d1 $m1 $ano
     >  > 'Outra Data: ' $d2 $m2 $ano
     >  > 'Mais uma data: ' $d3 $m3 $ano"
     >  > Data: 04/05/2015
     >  > Outra Data: 10/03/2015
     >  > Mais uma data: 05/12/2015
     >  >
     >  > Outro jeito que deu certo foi colocar apenas 'printf [formato]' entre 
aspas,
     >  > eval "printf '%20s%02d/%02d/%d\n'" $linha
     >  > ou
     >  > eval 'printf "%20s%02d/%02d/%d\n"' $linha
     >  >
     >  > No fim das contas o loop deu certo, mas eu não entendi porque.
     >  > Eu realmente achei que apenas colocando o printf dentro do loop teria 
que funcionar.
     >  > Porque o printf não reconhece direito a variável $linha sem o eval?



    ------------------------------------




----------------------------------------------------------------------------------------------------
Enviado por: "Julio C. Neves" <address@hidden>
----------------------------------------------------------------------------------------------------


reply via email to

[Prev in Thread] Current Thread [Next in Thread]