|
From: | Paulo Bettega |
Subject: | Re: [shell-script] printf em um loop while só funcionou com eval |
Date: | Sat, 31 Jan 2015 19:37:06 -0200 |
User-agent: | Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 |
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 [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 [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?
[Prev in Thread] | Current Thread | [Next in Thread] |