Come posso fare la divisione con variabili in una shell Linux?


136

Quando eseguo i comandi nella mia shell come di seguito, restituisce un expr: non-integer argumenterrore. Qualcuno può spiegarmelo?

$ x=20
$ y=5
$ expr x / y 
expr: non-integer argument

4
@ShivanRaptor Mentre si potrebbe sostenere che la domanda è una domanda RTFM, è certamente una domanda valida per la programmazione della shell. È anche una domanda ragionevole per qualcuno che proviene da lingue che non richiedono dereferenziazione (ad esempio Ruby o JavaScript). Dovrebbe essere lasciato aperto.
Todd A. Jacobs,

6
@ShivanRaptor No, questo è sull'argomento qui. Si tratta di programmare in Bash. Unix / Linux è principalmente per l'utilizzo del sistema, non per la programmazione. Ora, lo script di shell attraversa il confine tra la programmazione e l'uso del sistema, quindi questo potrebbe essere in argomento su entrambi i siti. Se ci fosse una domanda su "come faccio a impostare la rete", questo sarebbe sicuramente appartenente a Unix / Linux. Se fosse una domanda sulle combinazioni di tasti interattive in Bash, anche quella sarebbe di pertinenza. Ma una domanda sullo scripting di shell è sicuramente sull'argomento qui e là.
Brian Campbell,

Vedi qui la mia risposta, che illustra la sottrazione e la divisione di variabili $ BASH, usando una chiamata a Python dalla shell (per convertire int in float ...): stackoverflow.com/questions/8385627/…
Victoria Stuart

Risposte:


195

Quelle variabili sono variabili di shell. Per espanderli come parametri in un altro programma ( es. expr ), È necessario utilizzare il $prefisso:

expr $x / $y

Il motivo per cui si è lamentato è perché pensava che stessi cercando di operare su caratteri alfabetici ( cioè non interi)

Se stai usando la shell Bash, puoi ottenere lo stesso risultato usando la sintassi delle espressioni:

echo $((x / y))

O:

z=$((x / y))
echo $z

1
Puoi scoprire molto leggendo la man-page di bash. Digitare man bashal prompt ( qper uscire)
paddy

62
Va notato da qualche parte in questa pagina che la maggior parte (se non tutte) le shell GNU / Linux eseguono solo operazioni su numeri interi .
Skippy le Grand Gourou,

35

Credo che sia già stato menzionato in altri thread:

calc(){ awk "BEGIN { print "$*" }"; }

quindi puoi semplicemente digitare:

calc 7.5/3.2
  2.34375

Nel tuo caso sarà:

x=20; y=3;
calc $x/$y

o se preferisci, aggiungilo come script separato e rendilo disponibile in $ PATH in modo da averlo sempre nella tua shell locale:

#!/bin/bash
calc(){ awk "BEGIN { print $* }"; }

4
Puoi anche usareecho '1 / 3' | bc -l
Eugene il

19

Perché non usare let; Lo trovo molto più semplice. Ecco un esempio che potresti trovare utile:

start=`date +%s`
# ... do something that takes a while ...
sleep 71

end=`date +%s`
let deltatime=end-start
let hours=deltatime/3600
let minutes=(deltatime/60)%60
let seconds=deltatime%60
printf "Time spent: %d:%02d:%02d\n" $hours $minutes $seconds

Un altro semplice esempio: calcolare il numero di giorni dal 1970:

let days=$(date +%s)/86400

15

Fare riferimento alle variabili Bash richiede l'espansione dei parametri

La shell predefinita sulla maggior parte delle distribuzioni Linux è Bash. In Bash, le variabili devono utilizzare un prefisso del simbolo del dollaro per l' espansione dei parametri . Per esempio:

x=20
y=5
expr $x / $y

Naturalmente, Bash ha anche operatori aritmetici e una speciale sintassi di espansione aritmetica , quindi non è necessario invocare il file binario expr come processo separato. Puoi lasciare che la shell faccia tutto il lavoro in questo modo:

x=20; y=5
echo $((x / y))

Vedi Arithmetic Expansion e Shell Arithmetic nel Bash Reference Manual per tutti i dettagli cruenti.
Todd A. Jacobs,

1
Questo non ha nulla a che fare con la dereferenziazione ma l' interpolazione ed exprè scoraggiato nel 2013.
Gilles Quenot

@sputnick Sei chiaramente confuso. Non esitate a consultare un dizionario. Vedi dereference e interpolate .
Todd A. Jacobs il

1
Una parola migliore si sta espandendo , ma non dereferenziando . la dereferenziazione viene utilizzata quando utilizziamo i puntatori , non è questo il caso, sono solo semplici variabili.
Gilles Quenot

1
@Prashant: tldp non è noto per essere un buon riferimento nel mondo bash.
Gilles Quenot,

1

supponiamo

x=50
y=5

poi

z=$((x/y))

questo funzionerà correttamente. Ma se vuoi usare / operator in case case di quante non riesca a risolverlo. inserire il codice qui In quel caso usa stringhe semplici come div o devide o qualcos'altro. Vedi il codice


Questo è sbagliato. /funziona bene come un'etichetta shell-case. Ciò che non funziona è usare *per moltiplicare senza citarlo, che potrebbe essere quello che hai effettivamente fatto; che lo fa scavalcare efficacemente tutti gli elementi seguenti nel caso, che nel tuo esempio è 'devide' e 'modulo'
dave_thompson_085

0

Per ottenere i numeri dopo il punto decimale, è possibile eseguire questa operazione: -

read num1 num2
div=`echo $num1 / $num2 |bc -l`
echo $div
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.