Nello script di shell possiamo sostituire expr $a*$b
con $(($a+$b))
.
Ma perché non solo con (($a+$b))
, perché in qualsiasi risorsa è scritto che (())
è per il calcolo di numeri interi.
Quindi usiamo $(())
quando ci sono variabili invece di valori interi, vero? E cosa dovremmo usare al posto di $(())
quando le variabili possono ricevere valori float?
Commenti
- Vedi anche unix.stackexchange.com/questions/149823/…
Risposta
-
Per laritmetica,
expr
è arcaico. Non usarlo. * -
$((...))
e((...))
sono molto simili. Entrambi eseguono solo calcoli interi. La differenza è che$((...))
restituisce il risultato del calcolo e((...))
no. Pertanto$((...))
è utile nelleecho
istruzioni:$ a=2; b=3; echo $((a*b)) 6
((...))
è utile quando vuoi assegnare una variabile o impostare un codice di uscita:$ a=3; b=3; ((a==b)) && echo yes yes
-
Se vuoi floating calcoli in punti, utilizza
bc
oawk
:$ echo "4.7/3.14" | bc -l 1.49681528662420382165 $ awk "BEGIN{print 4.7/3.14}" 1.49682
* Per inciso, expr
rimane utile per la gestione delle stringhe quando i glob non sono abbastanza buoni ed è necessario un metodo POSIX per gestire le espressioni regolari.
Commenti
- Se expr è arcaico, cosa dovremmo usare al posto del testo expr: '. * '
- Se
s
è una variabile di shell, la sua lunghezza è${#s}
- $ {#} indica un numero di argomenti e $ (# s} indica un numero di caratteri di una variabile, vero?
- Sì. Questo ' è giusto.
- @Stranger Molti usi di
expr STRING : REGEX
possono essere scritti comecase STRING in PATTERN)
.expr
è utile solo quando REGEX può ' non essere espresso con caratteri jolly della shell.
Answer
expr è vecchio, ma mi viene in mente un uso limitato. Supponi di voler cercare una stringa. Se vuoi rimanere POSIX con grep, devi usare una pipe:
if echo november | grep nov then : do something fi
expr può farlo senza pipe:
if expr november : nov then : do something fi
lunico problema è che expr funziona con stringhe ancorate, quindi se vuoi trovare una corrispondenza dopo linizio devi cambiare REGEXP:
if expr november : ".*ber" then : do something fi
Per quanto riguarda (( ))
, questo costrutto non è POSIX , quindi dovrebbe essere evitato.
Per quanto riguarda $(( ))
, non è necessario includere il simbolo del dollaro:
$ fo=1 $ go=2 $ echo $((fo + go)) 3
Commenti
- Molti usi di
expr STRING : REGEX
possono essere scritti comecase STRING in PATTERN)
.expr
è utile solo quando REGEX può ' non essere espresso con caratteri jolly della shell.
Risposta
Sembra che i seguenti programmi facciano più o meno la stessa cosa e non differiscono realmente. Ma non è vero.
#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=$((s+1)) echo $s
Questo è il modo corretto per implementarlo. Lespressione s + 1 viene valutata dalla shell e può essere assegnata a una variabile.
#!/bin/bash s=-1000 for (( i=0; i<1000000; i++ )), do s=`expr $s+1` echo $s
Qui lespressione sarà calcolata dal programma expr, che non è” un builtin di shell ma un programma Unix esterno. Quindi, invece di aggiungere semplicemente 1 es, è necessario avviare un programma e il suo output deve essere letto e scritto nella variabile. Lavvio di un programma richiede molte risorse e molto tempo. E questo programma viene eseguito 1000000 volte. Quindi il programma sarà molto più lento del precedente. Tuttavia il codice funziona correttamente.
#!/bin/bash -e s=-1000 for (( i=0; i<1000000; i++ )), do ((s=s+1)) echo $s
Se il flag -e non è impostato, anche il programma funzionerà correttamente. Ma se -e è impostato quando s = -1 e ((s = s + 1)) viene calcolato. Lespressione s = s + 1 restituisce 0 e il codice di uscita di ((0)) è> 0, che viene interpretato come un errore dalla shell e la shell esce dal programma.
Il motivo per impostare il flag -e è che è il modo più semplice per elaborare gli errori: fermarsi se si verifica un errore.