Utilizzando expr, $ (()), (())

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

Risposta

  1. Per laritmetica, expr è arcaico. Non usarlo. *

  2. $((...)) e ((...)) sono molto simili. Entrambi eseguono solo calcoli interi. La differenza è che $((...)) restituisce il risultato del calcolo e ((...)) no. Pertanto $((...)) è utile nelle echo 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 
  3. Se vuoi floating calcoli in punti, utilizza bc o awk:

    $ 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 come case 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 come case 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.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *