Newsgroup: it.comp.os.linux.iniziare
Titolo: passare variabile ad un comando

+ cat a.sh
base_cmd="a=1 ./b.sh"
b=1 $base_cmd
#b=2 $base_cmd
#b=3 $base_cmd
#...
 
+ cat b.sh
echo $a-$b
 
+ bash ./a.sh
./a.sh: riga 2: a=1: comando non trovato
 
Perchè non va?


$cat a.sh
#!/bin/sh
base_cmd="a=5 ./b.sh"
eval b=1 $base_cmd
 
 
 
$cat b.sh
#!/bin/sh
echo $(($a-$b))
 
 
chmod +x a.sh b.sh
 
 
$./a.sh
4
 

 eval b=1 $base_cmd
 
bastava mettere eval :)

 bastava mettere eval :)
 
. ed aggiungerci un 'grazie' no?
 
 


Si, ma starei moooolto attento a quel "eval",
dato che fa proprio un "eval"...
 
Come al solito, perche` non spieghi cosa vuoi
fare, magari esiste una soluzione gia` fatta,
oppure un metodo "canonico".
 
"eval" e`, a mio avviso, cosa da molto esperti,
dato che *esegue* il parametro passato, quindi
se c'e` un comando, tipo "rm -rf *", potrebbe
anche fare danni...
 
bye,
 
-- 
 
piergiorgio



Il 02/03/2018 05:28, alex ha scritto:

echo $(($a-$b))
 


GRAZIE :)


#!/bin/sh
x=10 a=1 b=2 c=3 ./b.sh
x=20 a=1 b=2 c=3 ./b.sh
x=30 a=1 b=2 c=3 ./b.sh
x=40 a=1 b=2 c=3 ./b.sh
...
 
Per evitare di scrivere la stessa cosa ( a=1 b=2 c=3 ./b.sh ) ?

 Per evitare di scrivere la stessa cosa ( a=1 b=2 c=3 ./b.sh ) ?
 
Non ho capito niente di quello che vuoi fare.
 
Nel tuo esempio, a, b e c sono costanti, quindi
perche` passarle allo script?
Invece x parte da 10 e va avanti in step di 10,
si usa un loop.
 
Se proprio devi passare parametri, usa "getopt",
oppure semplicemente $1, $2, ...
 
In altre parole, esiste sicuramente un problema
simile al tuo con altrettante soluzione, che, di
solito, e` la piu` *semplice* possibile.
 
bye,
 
-- 
 
piergiorgio

 solito, e` la piu`*semplice*  possibile.
 
ok mi hai convinto, grazie :D
 

 Beh è un esempio, avrei anche potuto usare x=14 ...
 
C'e` il comando "seq", che genera sequenze (appunto),
usabili in un for loop.
 
Tipo:
 
for i in $( seq 14 3 32 )
do
  echo $i
done
 
"man seq" per dettagli.
 
Quindi, se il valore d'inizio, e magari
l'incremento, e` / sono variabili, si
possono passare con $1 $2 e poi fare il
loop di cui sopra.
 
Nota che il secondo parametro di "seq" e`
l'incremento, quindi *forse* il comando:
 
seq $1 $2 100
 
funziona con e senza $2 definito (non ho
provato, potrei sbagliarmi di grosso),
dato che:
 
seq 1 100
 
Conta da 1 a 100 in passi di 1 (default).
 
Chiaramente, se c'e` un terzo parametro
variabile (o secondo), le cose cambiano.
 
Concludendo, a seconda dell'uso, si puo`
giocare su $1, $2, ... in maniera opportuna.
 
bye,
 
-- 
 
piergiorgio

Il 07/03/2018 18:35, Piergiorgio Sartor ha scritto:
 >[...]
 
Grazie ancora, ma l'incremento potrebbe non essere regolare e nemmeno 
crescente
 
x=9 ...
x=2 ...
x=-3 ...
x=1000 ...
 
e potrebbe non essere neppure numerico
 
x=marco
 
:D


Ma per questo c'e` proprio "for" in shell:
 
for i in 9 2 -3 pippo pluto paperino 1000
do
  echo $i
done
 
Ovviamente la lista puo` essere passata anche
in vari modi...
"seq" semplicemente crea un lista specifica,
numerica, con partenza, fine ed incremento gia`
definiti.
 
D'altro canto, qualunque programma ("seq" e` un
eseguibile) puo` creare tale lista.
 
Quindi il problema e` semplicemente rendere semplice
come quella lista sia creata.
 
bye,
 
-- 
 
piergiorgio

 come quella lista sia creata.
 
Grazie ancora delle spiegazioni, cmq ti ripeto che il mio era 
fondamentalmente un esempio, naturalmente da rivedere alla luce di 
quanto emerso, prima di metterlo in funzione.

 quanto emerso, prima di metterlo in funzione.
 
Certo, era un esempio, ma di solito gli script si
scrivono per rendere facile un lavoro *ripetitivo*.
Non per generalizzare qualcosa.
 
Se il numero di parametri si avvicina alla complessita`
dello script, questo diventa inutile.
 
Quindi, per prima cosa, deve essere chiaro e chiarissimo
cosa si intenda fare (e perche`), poi si puo` discutere
su quale sia la migliore strategia.
Dove "migliore" sta per piu` semplice.
 
bye,
 
-- 
 
piergiorgio

 "man seq" per dettagli.
 
  Questo è da evitare:
 
1) il codice risultante è inefficiente: esegue una sottoshell e
bufferizzazione di I/O tra processi;
2) espande tutti i parametri che saranno usati nel ciclo prima della sua
esecuzione, usando più memoria del necessario;
2) lavorasse su dati variabili o su input arbitrari espone la shell ad
attacchi di esaurimento della memoria.
 
  Quello che si deve fare è:
 
for ((I=14; I<=32; I=$((I+3)) ))
do echo $I
done
 
oppure, si stesse usando una bash versione < 4:
 
I=14
while test $I -le 32
do echo $I
   I=$((I+3))
done
 
 
  Ciao,
 
 
-- 
Alessandro Selli 
http://alessandro.route-add.net
 
AVVERTENZA: i messaggi inviati a "trappola" non mi arriveranno.
WARNING: messages sent to "trappola" will never reach me.

 done
 
Non sarei sicuro che questi siano piu` veloci dei
due programmi combinati, soprattutto per liste lunghe.
 
Nel casa; "for ... seq", prima viene generata la lista
e poi il loop la scorre. Quindi accede a dati statici,
come tu stesso fai notare sopra.
I secondi casi *devono* sempre essere *interpretati*
da bash, con un'ovvia penalita` prestazionale.
 
Detto altrimenti, c'e` la possibilita` che "seq" sia
piu` veloce a generare la lista, di quanto non sia
bash ad interpretare la stessa cosa.
 
Questa cosa diventa evidente in molti altri casi,
quando l'overhead dovuto all'uso di due processi
(o piu`) processo e` minore dell'overhead dovuto
a bash che interpreta lo script.
 
Infine, se proprio vogliamo parlare di prestazioni,
al giorno d'oggi potrebbe anche essere meglio:
 
seq ... | xargs -P x -n y -r cmd
 
bye,
 
-- 
 
piergiorgio

> done
 
Io ci metterei, proprio volendo evitare di generare
la sequenza in anticipo, anche:
 
seq 14 3 32 | while read I
do
  echo $I
done
 
Questo funziona con ogni lista (fino ai limiti di "read")
e non dovrebbe allocarsi tutto in un colpo.
 
bye,
 
-- 
 
piergiorgio

 seq ... | xargs -P x -n y -r cmd
 
  Non credo migliori i rischi.


   Non credo migliori i rischi.
 
Non ha nessun rischio, dato che esegue "x"
processi in parallelo (con "x" costante e non
variabile), ognuno con "y" parametri, tipicamente
1, ma potrebbero essere di piu` (anche qui "y" e`
costante).
E` la versione parallela del tuo codice, solo che
dato che usa "|" puo` funzionare con qualunque
programma generi la lista.
 
Cioe` partono "x" processi, per es. 4, ognuno
dei quali consuma "y" valori e non c'e` nessun
rischio di allocare troppa memoria o CPU.
Il parallelismo, se sfruttato bene, cioe` con
"x" e "y" giusti, consente di ottenere risultati
ottimali.
 
Vi sono programmi migliori di "xargs", come "parallel"
od altri forse, dipende da cosa si vuole fare.
 
bye,
 
 
-- 
 
piergiorgio