Newsgroup: it.comp.os.linux.iniziare
Titolo: programmazione non strutturata in bash

tornando alla preistoria, ho bisogno di inserire in uno script bash un
comando tipo "goto" che consente di saltare da una parte all'altra del
file incondizionatamente.
tale istruzione era presente in dos, basic, pascal e tutt'ora ancora
presente in C.. c'è in bash?
nel man non ho visto nulla di simile.
Grazie, Matteo

 presente in C.. c'è in bash?
Grazie a dio, no.
GOTO e' MALE. Impara a fare un ciclo "for".
-- 
Best Regards, Jack
Linux user #264449
Powered by Debian Sid AMD64

 ... prova tcsh.
 
Il rimedio e' peggiore del male

Matteo Rossini wrote:

incondizionatamente vuol dire senza nessun test?
se il tuo codice lo scrivi come insieme di funzioni?

 GOTO e' MALE. Impara a fare un ciclo "for".
D'accordo con la prima parte ma io lavorerei con il 
ciclo while ed il case.
Senza contare che con la bash anche un ciclo for e' 
da usare con cautela.  

 da usare con cautela.
!?
-- 
By ZeD

 file incondizionatamente.
non *vuoi* farlo.
"rifattorizza" (bum! paroloni in libertà) il tuo codice per usare i classici
if, for e compagnia bella. ti consiglio di organizzare il tuo codice anche
in funzioni, ti renderà le cose più facili.
-- 
By ZeD

 file incondizionatamente.
No...anch'io pensavo tempo fa me lo sono chiesto, ma non ho
trovato nulla, quindi, meglio strutturare i blocchi di codice in
modo da potervi accedere alla bisogna. Con le funzioni cicli
for, while, e qualche costrutto condizionale dovresti cavartela in
ogni caso.  ;-)

si,si, sono daccordo con tutti voi (tranne che mallin.shetland che mi
deve spiegare perchè la for è male...)
lo sapevo già. La mia professoressa diceva che se trovava una sola
goto nei listati la bocciatura era sicura.
ma io non credo che, se usata come si deve, possa rompere la
programmazione strutturata.
cmq vado con l'esempio concreto.
in questo momento mi stò vedendo un po' le trap.
il caso attuale è abbastanza semplice da gestire.
#!/bin/bash
trap "ctrlc" 2
function azione1 () {
    ....
}
function azione2 () {
   ...
}
function ctrlc () {
   echo "ctrl+c premuto... interrompo la funzione e torno al menù"
   continue 100
}
while true;do
   echo "menù principale. premi 1 per azione1, 2 per azione2, 0 per
uscire"
   read scelta
   case $scelta in
      1) azione1;;
      2) azione2;;
      0) exit;;
      *) echo "errore";;
   esac
done
credo che lo script sia abbastanza chiaro.
ho un menù e l'utente deve scegliere tra una delle azioni.
se durante l'esecuzione delle azioni viene premuto ctrl+c, viene
avviata la trap che chiama
la funzione ctrl+c che semplicemente chiama la funzione 'continue' per
ritornare all'inizio del ciclo while principale
questo è un caso semplice. un caso più complicato potrebbe essere
quello che prevede di scoprire cosa stava facendo il programma per
chiudere, ad esempio, alcuni file lasciati aperti, o decidere a
seconda dei casi di non tornare al menù, ecc...
è chiaro che non voglio usare il goto per saltare a destra e a manca
in uno script senza criterio (non oso pensare alla manutenzione di uno
script del genere).
Ciao,
Matteo

 done
ma se metti il ciclo while in una funzione (loop?) che poi invochi al
CTRL-C?
-- 
By ZeD


beh, se metto la while nel main o in una funzione chiamata dal main
non cambia nulla.
#!/bin/bash
   trap "ctrlc" 2
function azione1 () {    ....   }
function azione2 () {    ...  }
function ctrlc () { ...  }
function menu () {
   while true;do
      ...
   done
}
menu
comunque la soluzione adottata funziona, ma, come dicevo, questo è un
caso semplice
ma nel caso in cui al ctrl+c si deve far uno stop di tutto quello che
stava facendo il programma, menù incluso, e fargli fare tutt'altra
cosa, le cose cambiano e si complicano non poco.
Matteo

 ... mi deve spiegare perchè la for è male...)
No, non era mia intenzione di dire nulla del genere ne` mi
pare di averlo detto; l'istruzione for è una istruzione 
rispettabilissima ed è bene usarla.
Pero` in questo contesto voglio porre due questioni che 
possiamo definire dii stile in risposta a Jack Malmosto. 
La prima riguarda l'uso del for come struttura iterativa. 
In alcuni linguaggi e` un costrutto molto limitato che 
semplicemente non ha la potenza del while per cui in 
questi casi e' meglio usare il  while. 
In altri linguaggi, come il C o la bash, il for e` un 
costrutto molto piu' generale del while che va usato 
con cautela quando non si tratta di fare un ciclo 
controllato da un contatore; se questo non e` il caso 
usando il while ne guadagnano la leggibilita` e la 
portabilita'.
La seconda questione riguarda i due for della bash.
Il costrutto for ... in ed il for aritmetico servono
in casi particolari; nel caso generale si usa il while. 

 menu
-- 
By ZeD

 portabilita'.
?!?!?!
ma quando mai!?
0) è perfettamente possibile avere un linguaggio di programmazione
turing-completo che offra solo i costrutti di sequenza (A; B; C) e
il "ciclo while" (o, se preferisci, solo con la ricorsione, pero' quello è
un altro discorso)
1) il ciclo for del C e il ciclo for della bash sono "concettualmente" un
po' diversi:
nel primo caso hai 4 parametri: "statement iniziali" (superfluo, potrebbero
essere messi prima del costrutto stesso), "condizione di arresto"
e "statement di passo", "corpo del ciclo"
nel secondo hai 2 parametri: "contenitore di dati" (+ nome a cui associare
il dato corrente) e "corpo del ciclo".
2) Nel caso del c, il ciclo while e il ciclo for sono perfettamente
trasformabili l'uno nell'altro (tant'è che il ciclo for è "zucchero
sintattico" per il ciclo while)
"statement iniziali"
while ("condizione di arresto") {
  "corpo del ciclo"
  "statement di passo"
}
è equivalente a
for ("statement iniziali", "condizione di arresto", "statement di passo") {
  "corpo del ciclo"
}
3) è infine vero che il ciclo for della bash e quello del c *non* sono
perfettamente equivalenti tra loro: il primo non ha la possibilità di
generare cicli infiniti, mentre il secondo può simulare perfettamente il
primo.
questo ciclo di bash
for EL in el1 el2 el3; do
  do_something $EL
done
è esprimibile in C (tralascio i tipi per semplicità) come
array = {el1, el2, el3};
size = 3;
for (i=0; i<size; i++) {
  el = array[i];
  do_something(el);
}
(tra l'altro, penso sia molto più leggibile il primo costrutto, ma qui si
entra nel personale)
al contrario, non è possibile convertire cicli di durata non prevedibile a
priori dal C in bash.
trovami, infatti, un modo convertire for (;;) { ... } o while (1) { ... }
del C nell'equivalente in bash usando solo il costrutto for
-- 
By ZeD

 del C nell'equivalente in bash usando solo il costrutto for
Vedi sopra.
for ((;1;));do
  ...
done

 done
Anzi, ho visto ora che funziona addirittura anche questo:
for ((;;));do
  ...
done

 done
beh, si :)
anche se, volendomi attaccare al capello:
$ help for
for: for NAME [in WORDS ... ;] do COMMANDS; done
    The `for' loop executes a sequence of commands for each member in a
    list of items.  If `in WORDS ...;' is not present, then `in "$@"' is
    assumed.  For each element in WORDS, NAME is set to that element, and
    the COMMANDS are executed.
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
    Equivalent to
        (( EXP1 ))
        while (( EXP2 )); do
                COMMANDS
                (( EXP3 ))
        done
    EXP1, EXP2, and EXP3 are arithmetic expressions.  If any expression is
    omitted, it behaves as if it evaluates to 1.
$
il costrutto di cui parlavo io (l'unico che conoscevo) è effettivamente il
for, mentre quello che dici tu è "il costrutto" 'for ((' :p
tra l'altro, è esplicitato nella documentazione stessa l'equivalenza con il
ciclo while (tra l'altro neanche sapevo che "nel mio" for la parte "in
WORDS ...;" fosse opzionale)
-- 
By ZeD

 for, mentre quello che dici tu è "il costrutto" 'for ((' :p
E' vero, non avevo mai provato ad eseguire "help for" :-)