Newsgroup: it.comp.os.linux.sys
Titolo: Curiosita' in bash script ...

Ciao a tutti.
Prima di rendermi conto che mi accingevo a riscoprire l'acqua calda mi
sono imbattuto in una curiosita' di cui non riesco a venire a capo.
Spero che qualcuno possa aiutarmi a chiarire il mistero ...
[Debian/Woody 3.01, k 2.2.22]
-----------------------------
Lanciando questo script (qui depurato da tutti i fronzoli ed i vari
tentativi fatti):
#!/bin/sh -x
echo Input the number you whish to translate:
read num
echo "Il numero inserito e': $num"
l_num=${#num[0]}
if test "$l_num" -gt 7; then
   echo -e "Sorry! The number given has ($l_num) figures\c"
   echo " and is out of my range."
else
   echo "The given number has $l_num figures"
fi
# Proviamo un'alternativa:
e=0
for (( i=1; i<=$l_num; i++ )) ; do
 set -xv
set b_$i=`echo "$num" |cut -c$i`  ##ok anche senza doppi apici "$num"
-------- nota
# ok, questa istruzione mostra che b_1=1 e b_2=1 (se num=11)
# ma, poi, quando richiamo le variabili, hanno un valore diverso!
# echo $b_i"$i"  questo est b_$i  ## e mi da b_1=1, b_2=2 !!!
--------
echo $b_"$i" questo est b_1
set - 
 echo $e questo est e
   echo $((16**$e))*$b_$i ## notaz. provv. per vedere cosa scrive
   e=`expr $e + 1`
   if [ "$e" -gt "$l_num" ] ; then
      echo "finiti"
   exit 1
   fi
done
###################################################
Questo e' il risultato del debug di: $ sh my_calc.sh:
-----------------------
my_calc.sh
To translate hex-numbers to decimal-numbers
Input the number you whish to translate:
Il numero inserito e': 11
The given number has 2 figures
echo "$num" |cut -c$i
++ echo 11
++ cut -c1
+ set b_1=1               ## nota: il valore di b_1 e' corretto
+ echo 1 questo est b_1
1 questo est b_1
+ set -
0 questo est e
1*1
echo "$num" |cut -c$i
++ echo 11
++ cut -c2
+ set b_2=1               ## ok, giusto, ma ...
+ echo 2 questo est b_1   
2 questo est b_1          ## da dove esce fuori questo 2?
^ ^^^^^^^^^^^^^^             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ set -
1 questo est e
16*2                      
   ^
_________________________________________
Uso, forse, in modo scorretto l'assegnazione ad una variabile del
risultato di un comando? Sembrerebbe di no, perche' in prima istanza il
valore risulta giusto.
Allora il problema sta nel richiamare quel valore ... boh?
Grazie dell'attenzione.
-- 
[Perche' usare Win$ozz (dico io) se ..."anche uno sciocco sa farlo.    \\?//
 Fa' qualche cosa di cui non sei capace!"   (diceva Henry Miller) ]    (°|°)
 Ennio. (Please change . for .dot. and @ for .at. in my Reply-To)       )=(

 Allora il problema sta nel richiamare quel valore ... boh?
Temo che ci sia piu` da porsi domande d'altro tipo in particolar modo:
interpretazione/espansione della shell.
adeguatezza della shell per questi compiti.
detto tra noi:
mizio@hal:~$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
ibase=10
obase=16
250
FA
123
7B
11
B
quit
mizio@hal:~$ 
-- 
                          Maurizio - Tannoiser - Lemmo
                 Founder Member of ERLUG 
http://erlug.linux.it
-------------------------------------------------------------------------------
An NT server can be run by an idiot, and usually is.

 mizio@hal:~$ bc
        ^^^
Mizio, stai attento con quel "coso"; una volta un mio amico e' stato
catapultato fuori dal suo modulo spaziale, perche` il "coso" gli ha
letto il labbiale :-)
Banana che talvolta e' proprio un'odissea :-)

 Mizio, stai attento con quel "coso"; 
*gh*.
E che ormai ho perso fantasia. Avevo liste di nomi assolutamente
improbabili. Sto invecchiando. :)


 2 questo est b_1          ## da dove esce fuori questo 2?
Forse mi sbaglierò, ma secondo me, quel 2 è $i.
Da qualche prova fatta, mi sembra che il problema sia nella variabile 
b_$i, se provi mettendo come num un altro valore tipo 34 vedrai che 
avrai lo stesso risultato, a dimostrazione che lo script legge b_ 
staccato da $i.
Devi usare un array, b[$i] al posto di b_$i.
Ciao, Paolo

 Devi usare un array, b[$i] al posto di b_$i.
Così infatti mi sembra proprio che funzioni.
#!/bin/sh
num=11
for (( i=1; i<=2; i++ )) ; do
b[$i]=`echo "$num" |cut -c$i`
echo ${b[$i]} questo est b
done

* Kaosmos <unaltr...@TOGLIvirgilio.it> [Thu, 18 Mar 2004 at 19:03 GMT]:

Ebbene, si, funziona :-)))))
Le stavo tentando tutte ed ho quasi riempito due pagine di prove
sballate. Ma ... curiosita' per curiosita', in quale sezione di bash
avrei potuto trovare la soluzione? [Ho letto piu' volte la <command
substitution> e relative voci, ma non ho visto nulla! Anche gli esempi
trovati su Google non mi hanno illuminato molto (per questo specifico
problema, naturalmente)].
Comunque, moltissime grazie: potro` impiegare il tempo in altre letture
:-)
Ciao.


  [cut]
Ti ringrazio, lo conosco. Il fatto e` che voglio fare un po' di pratica
non gli script e capire come/perche' funzionano le cose e' importante
:-)
Grazie del contributo. Ciao.


 non gli script e capire come/perche' funzionano le cose e' importante
Hai assolutamente ragione, ma anche la scelta dello strumento "aiuta".
Per fare pratica di programmazione, _forse_ la shell, per il suo
orientamento all'interattivita` e alla gestione del sistema, non e`
molto indicata.
Probabile che tu possa trovare strumenti piu` utili ed educativi in
linguaggi di programmazione piu` orientati alla programmazione.
(il caso di bc, era piu` per simpatia, ovviamente e perche` magari altri
non lo conoscono).
-- 
                          Maurizio - Tannoiser - Lemmo
                 Founder Member of ERLUG 
http://erlug.linux.it
-------------------------------------------------------------------------------
sigfault

 Comunque, moltissime grazie: potro` impiegare il tempo in altre letture
Figurati, io imparato anche io qualcosa :-)
Ciao, Paolo

 Comunque, moltissime grazie: potro` impiegare il tempo in altre letture
Figurati, ho imparato anche io qualcosa :-)
Ciao, Paolo

  linguaggi di programmazione piu` orientati alla programmazione.
Pensi a C, Java, Perl, Python?
Sai quale di questi potrebbe piu` celermente darmi la possibilita` di
creare le macro necessarie a sostituire efficacemente i miei lotus.123
(fatti con Lotus Millennium) con f.e. di OpenOffice? 


  davvero interessante.
Si, questa l'ho spulciata qua e la` : merita un approfondimento ...
Di nuovo grazie dei suggerimenti e ... della soluzione :-)
Ciao,
	Ennio


  Spero che qualcuno possa aiutarmi a chiarire il mistero ...
[cut]
OK, e` la scoperta dell'acqua calda, che gia` fanno bash e chissa`
quante altre applicazioni (tra cui bc).  Pero` sono tanto contento che,
rischiando qualche rabbuffo dai piu` ligi alla 'net-etiquette', lo
voglio mettere a disposizione del mondo.
E' anche un modo, d'altronde, per ri-ringraziare chi mi ha aiutato a
proseguire :-)
quote:
--------------------------------------------------------------
#!/bin/sh -x
# my_calc
# per trasformare un numero esadecimale in decimale
# ovvero "scoperta dell'acqua calda", visto che bash lo fa gia`
# $ echo $((0xnumhex)) -> equivalente decimale
# Author: nasr-laili alias Ennio-Sr
# Date: 16 marzo 2004
# Version: Beta-0.0.0.0.1 !!!
clear
echo my_calc.sh
echo To translate hex-numbers to decimal-numbers
echo; echo
echo Input the number you whish to translate:
echo; echo
read num
echo
echo "Il numero inserito e': $num"
echo; echo
l_num=${#num[0]}
if test "$l_num" -gt 7; then
   echo -e "Sorry! The number given has ($l_num) figures\c"
   echo " and is out of my range."
else
   echo "The given number has $l_num figures"
fi
echo; echo
tot=0
e=$(($l_num-1))    ## attenzione a come si scrive! (cfr. es. 10-14 
		   ## Scripting Guide
for (( i=1; i<=$l_num; i++ )) ; do
b_[$i]=`echo "$num" |cut -c$i`  ##ok anche senza doppi apici "$num"
if [ "${b_[$i]}" = "A" -o "${b_[$i]}" = "a" ] ;then
   b_[$i]="10"
   elif [ "${b_[$i]}" = "B" -o "${b_[$i]}" = "b"] ;then
      b_[$i]="11"
      elif [ "${b_[$i]}" = "C" -o "${b_[$i]}" = "c"] ;then
         b_[$i]="12"
         elif [ "${b_[$i]}" = "D" -o "${b_[$i]}" = "d"] ;then
            b_[$i]="13"
            elif [ "${b_[$i]}" = "E" -o "${b_[$i]}" = "e"] ;then
               b_[$i]="14"
               elif [ "${b_[$i]}" = "F" -o "${b_[$i]}" = "f"] ;then
                  b_[$i]="15"
fi   
s[$i]=`echo $((16**$e*${b_[$i]}))`
tot=$(($tot+${s[$i]}))     ## Questo accumula i parziali
e=`expr $e - 1`
if [ "$e" -gt "$l_num" ] ; then
   echo "finito"
  exit 1
fi
done
for (( i=1; i<=$l_num; i++ )) ; do
   echo ${s[$i]}  ## ok questa elenca i risultati
done
echo; echo
echo -n "The equivalent decimal number of $num is: "
echo $tot  ## e questo li stampa
--------------------------------
This program is protected under GNU Public Licence etc. etc. etc.
e ...
se vi ci divertite, potete inviarmi 1 euro al mio e-mail, cosi' ci pago
la prossima bolletta Enel :-)))
Ciao a tutti e ... grazie.
	Ennio.


     elif [ "${b_[$i]}" = "B" -o "${b_[$i]}" = "b"] ;then
                                                   ^
Attenzione: 1° bug: aggiungere spazio prima della ']'


 (fatti con Lotus Millennium) con f.e. di OpenOffice? 
Per diffusione e disponibilita` di moduli ed estensioni, (rimanendo ai
solo interpretati), dico perl, e poi python.
Nota di spirito: il tuo script precedente, in perl e` grosso modo cosi`:
#!/usr/bin/perl
print "Please press CTRL-D for terminate\n";
while (<>) {
print hex $_;
print "\n";
}
O monoriga che fa piu` ridere: perl -ne 'print hex ; print "\n"'
[*]
No, delphi non e` pascal. Si, era un battuta spiritosa, non un
affermazione di principio.


  O monoriga che fa piu` ridere: perl -ne 'print hex ; print "\n"'
Indubbiamente sintetico. Penso che daro` uno sguardo alla
documentazione sperando di trovarci quanto mi serve ...
Ma, spirito per spirito : Vuoi mettere il programma fatto da me, rapido
ed immediato ( calc / numero ) con quelli ufficiali? (suppongo: richiama
perl / chiama il prog / ins. numero / esci da perl; oppure, per il piu`
immediato 'echo $((0xnum))' scrivere tutte quelle parentesi? :-)
A proposito, sono gia` alla versione 0.0.0.4, che verifica anche il
risultato con echo $(...  :-)))
Grazie dei suggerimenti. Ciao.
-----------
P.S.: Tuo header '* Maur ...' > 72 costringe a re-editing :-)


 P.S.: Tuo header '* Maur ...' > 72 costringe a re-editing :-)
Ehm: dipende da una _tua_ impostazione. E` quello che il tuo newsreader
riporta del messaggio a cui risponde. Infatti il mio e` configurato per
data e nome (e non anche la mail) se no uscirebbero quasi tutti > 72.
-- 
                          Maurizio - Tannoiser - Lemmo
                 Founder Member of ERLUG 
http://erlug.linux.it
-------------------------------------------------------------------------------
If you lie to the compiler, the compiler will get its revenge.

  
Oops ... touché: mi mancava un <\n> nella followup_string di .slrnrc ...
Non si finisce mai di imparare :-)
Ciao.


 [Ma prima o poi li capiro` ... ;) ]
Vero. E d'altra parte e` programmazione. Essa e` addetta ai lavori.
Ciao.
-- 
                          Maurizio - Tannoiser - Lemmo
                 Founder Member of ERLUG 
http://erlug.linux.it
-------------------------------------------------------------------------------
A good system can't have a weak command language.

 [big-cut]
Ti ringrazio, le tue indicazioni mi aiutano a cercare la strada: su
Google, Appunti e Scripting Guide spero di trovare degli esempi :-)


 [Thu, 18 Mar 2004 at 17:47 GMT]:
Proseguendo nei miei esperimenti di bash scripting mi sono imbattuto in
un comportamento di bash che non riesco a capire.
Lo script (ridotto all'osso) e`:
--------------------------
#!/bin/sh -x
# my_bin2
# per trasformare un numero binario in decimale
# [Bash lo fa, ma io non ho capito come ... :-) ]
# 20 marzo 2004
clear
while test 1  ; do
echo my_calc.sh
echo To translate hex-numbers to decimal-numbers
echo "        (Input '-1' to exit)"
echo; echo
echo Input the number you whish to translate:
echo; echo
read -p \-----\>" " num ; 
set -xv
l_num=${#num[0]}
if test "$l_num" -gt 12; then
   echo -e "Sorry! The number given has ($l_num) figures\c"
   echo " and is out of my range."
else
   echo "The given number has $l_num figures"
fi
echo
if test "$num" -le "-1" ; then
   exit 1
fi   
set -
echo
echo "Il numero inserito e': " $num
echo; echo
sleep 2 ## qui aspetta per consentire lettura 
tot=0
e=$[$l_num-1]      ## attenzione a come si scrive!
for (( i=1; i<=$l_num; i++ )) ; do   ## cosi' inverte ordine cifre
b_[$i]=`echo "$num" |cut -c$i`  ##ok anche senza doppi apici "$num"
s[$i]=`echo $((2**$e*${b_[$i]}))`
tot=$(($tot+${s[$i]}))
   e=`expr $e - 1`
done
for (( i=1; i<=$l_num; i++ )) ; do
   echo  ${s[$i]}  ## ok questa elenca i risultati
done
echo; echo
echo -n "The equivalent decimal of binary $num is: "
echo $tot
echo
#echo -e "And ... if you don't trust me, this is the result of\c "
#echo " echo\$((0x$num))" :
#echo
### echo -n "                        " $((2x$num))
#echo
echo ________________________________________________________________________
done
----------------------
Lo script completo accetta fino a 32 caratteri, che formatta dividendoli
in gruppi di 4 per una piu` agevole lettura. La curiosita` irrisolta e`
che, a partire da un num. binario di 11 cifre, pur continuando a fornire
la risposta corretta dell'equivalente decimale, mi spara un warning: 
.......
+ test 11111111111 -le -1
/.../.../my_bin2.sh: test 11111111111: integer expression expected
.......
che, se interpreto correttamente, ha a che vedere con il limite di
rappresentazione degli interi (inferiore a 11 cifre).
Ma perche` poi prosegue e da` un risultato corretto?
Grazie dell'attenzione
	Ennio


 fi   
L'errore ti viene fuori da questo test e non ha nulla a che vedere con 
il limite di 11 caratteri.
Come puoi leggere qui (
http://ildp.pluto.linux.it/guide/abs/ops.html
) in 
bash le variabili intere devono essere comprese tra -
2147483648
 e 
2147483647
 e se superi questi limiti ti dà errore.
Nell'input non hai problemi perchè la variabile è trattata come stringa, 
ma qui tu la forzi a essere presa come numero intero e quindi scatta il 
limite.
Nel tuo caso per superare il problema dovrebbe essere sufficiente 
trattare la variabile come stringa anche nel test e quindi fare:
if test "$num" = "-1"; then
	exit 1
fi
Se non sbaglio il limite per le stringhe è 256 caratteri, quindi ci 
rientri tranquillamente!
Comunque questi tuoi esperimenti mi stanno facendo imparare un sacco di 
cose pure a me ;-)
Ciao, Paolo

  cose pure a me ;-)
Oh, questo mi fa molto piacere e, visto che gradisci, te ne regalo una
fortissima (formatta dalla 29 alla 32 cifra) :
   elif test "$l_num" -ge "29" -a "$l_num" -le "32" ; then
      num_ft1=`echo "$num" |cut -c1-$(($l_num-28)) ; echo "$num" |cut\
      -c$(($l_num-27))-$(($l_num-24)) ; echo "$num" | cut\
      -c$(($l_num-23))-$(($l_num-20)) ; echo "$num" | cut\
      -c$(($l_num-19))-$(($l_num-16)) ; echo "$num" | cut\
      -c$(($l_num-15))-$(($l_num-12)) ; echo "$num" | cut\
      -c$(($l_num-11))-$(($l_num-8)) ; echo "$num" | cut\
      -c$(($l_num-7))-$(($l_num-4)) ; echo "$num" | cut\
      -c$(($l_num-3))-$(($l_num))`
 
Se l'avessi vista scritta da qualche parte non ci avrei creduto: potenza
di una bash! :-)
Ciao e ... grazie,
	Ennio.


 di una bash! :-)
Non so se mi tornerà utile, ma ti ringrazio del "regalo" :-)
Comunque la bash è davvero potente, c'è poco da dire.
Ciao, Paolo

  
Nope! Tentato in tutte le salse ... (il progr. continua, naturalmente, e
da` il risultato giusto). Intanto rileggo la Abs, ma non ci sara` mica
qualche opzione speciale da abilitare? Pero` se do` (da console: $
enable -p mi sembrano tutte abilitate e, comunque, 'test' lo e`!).
Ciao,


  da` il risultato giusto). Intanto rileggo la Abs, .......
leggendo la quale, ho provvisoriamente risolto sostutuendo con:
case "$num" in "" )
   exit 1;;
esac
Ciao : -)
