Wie kann ich mit Variablen in einer Linux-Shell teilen?

136

Wenn ich Befehle in meiner Shell wie folgt ausführe, wird ein expr: non-integer argumentFehler zurückgegeben. Kann mir bitte jemand das erklären?

$ x=20
$ y=5
$ expr x / y 
expr: non-integer argument
Judking
quelle
4
@ShivanRaptor Während man argumentieren könnte, dass die Frage eine RTFM-Frage ist, ist es sicherlich eine gültige Shell-Programmierfrage. Dies ist auch eine vernünftige Frage für jemanden, der aus Sprachen stammt, für die keine Dereferenzierung erforderlich ist (z. B. Ruby oder JavaScript). Es sollte offen bleiben.
Todd A. Jacobs
6
@ShivanRaptor Nein, das ist hier zum Thema. Es geht um das Programmieren in Bash. Unix / Linux dient hauptsächlich zur Verwendung des Systems, nicht zur Programmierung. Jetzt überschreitet Shell-Scripting die Grenze zwischen Programmierung und Verwendung des Systems, sodass dies auf beiden Websites zum Thema gehören kann. Wenn es eine Frage zum Thema "Wie richte ich ein Netzwerk ein?" Gab, würde dies definitiv zu Unix / Linux gehören. Wenn es sich um eine Frage zu interaktiven Tastenkombinationen in Bash handeln würde, würde dies auch dazu gehören. Aber eine Frage zum Shell-Scripting ist sowohl hier als auch dort definitiv ein Thema.
Brian Campbell
Siehe meine Antwort hier, die die Subtraktion und Division von $ BASH-Variablen unter Verwendung eines Aufrufs von Python aus der Shell veranschaulicht (um int in float umzuwandeln ...): stackoverflow.com/questions/8385627/…
Victoria Stuart

Antworten:

195

Diese Variablen sind Shell-Variablen. Um sie als Parameter für ein anderes Programm ( dh expr ) zu erweitern, müssen Sie das $Präfix verwenden:

expr $x / $y

Der Grund, warum es sich beschwert hat, ist, dass es dachte, Sie wollten mit alphabetischen Zeichen ( dh nicht ganzzahligen Zeichen ) arbeiten.

Wenn Sie die Bash-Shell verwenden, können Sie mit der Ausdruckssyntax dasselbe Ergebnis erzielen:

echo $((x / y))

Oder:

z=$((x / y))
echo $z
Paddy
quelle
1
Sie können viel herausfinden, indem Sie die Manpage für Bash lesen. Geben Sie man bashan der Eingabeaufforderung ( qzum Beenden)
Paddy
62
Es muss irgendwo auf dieser Seite angemerkt werden, dass die meisten (wenn nicht alle) GNU / Linux-Shells nur ganzzahlige Operationen ausführen .
Skippy le Grand Gourou
35

Ich glaube, es wurde bereits in anderen Threads erwähnt:

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

dann können Sie einfach eingeben:

calc 7.5/3.2
  2.34375

In Ihrem Fall wird es sein:

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

oder wenn Sie es vorziehen, fügen Sie dies als separates Skript hinzu und stellen Sie es in $ PATH zur Verfügung, damit Sie es immer in Ihrer lokalen Shell haben:

#!/bin/bash
calc(){ awk "BEGIN { print $* }"; }
zielonys
quelle
4
Sie können auch verwendenecho '1 / 3' | bc -l
Eugene
19

Warum nicht let verwenden? Ich finde es viel einfacher. Hier ist ein Beispiel, das Sie vielleicht nützlich finden:

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

Ein weiteres einfaches Beispiel: Berechnen Sie die Anzahl der Tage seit 1970:

let days=$(date +%s)/86400
Mike Behr
quelle
15

Das Referenzieren von Bash-Variablen erfordert eine Parametererweiterung

Die Standard-Shell bei den meisten Linux-Distributionen ist Bash. In Bash müssen Variablen ein Dollarzeichenpräfix für die Parametererweiterung verwenden . Beispielsweise:

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

Natürlich verfügt Bash auch über arithmetische Operatoren und eine spezielle arithmetische Erweiterungssyntax , sodass die expr- Binärdatei nicht als separater Prozess aufgerufen werden muss. Sie können die Shell die ganze Arbeit so machen lassen:

x=20; y=5
echo $((x / y))
Todd A. Jacobs
quelle
Weitere Informationen finden Sie im Bash-Referenzhandbuch unter Arithmetische Erweiterung und Shell-Arithmetik .
Todd A. Jacobs
1
Dies hat nichts mit Dereferenzierung zu tun, sondern mit Interpolation und exprwird 2013 nicht
empfohlen
@sputnick Du bist eindeutig verwirrt. Bitte konsultieren Sie ein Wörterbuch. Siehe Dereferenzierung und Interpolation .
Todd A. Jacobs
1
Ein besseres Wort ist das Erweitern , aber nicht das Dereferenzieren . Dereferenzierung wird verwendet, wenn wir Zeiger verwenden , das ist hier nicht der Fall, das sind nur einfache Variablen.
Gilles Quenot
1
@Prashant: tldp ist nicht als gute Referenz in der Bash-Welt bekannt.
Gilles Quenot
1

Gesetzt den Fall

x=50
y=5

dann

z=$((x/y))

Dies wird ordnungsgemäß funktionieren. Wenn Sie jedoch / operator in case-Anweisungen verwenden möchten, kann dies nicht behoben werden. Code hier eingeben Verwenden Sie in diesem Fall einfache Zeichenfolgen wie div oder devide oder etwas anderes. Siehe den Code

Pooja Rajput
quelle
Das ist falsch. /funktioniert gut als Shell-Case-Etikett. Was nicht funktioniert, ist die *Multiplikation, ohne sie zu zitieren. Dies könnte das sein, was Sie tatsächlich getan haben. dass Ursachen es effektiv alle folgenden Elemente im Fall außer Kraft zu setzen, die in Ihrem Beispiel ist ‚Divide‘ und ‚Modulo‘
dave_thompson_085
0

Um die Zahlen nach dem Dezimalpunkt zu erhalten, können Sie Folgendes tun: -

read num1 num2
div=`echo $num1 / $num2 |bc -l`
echo $div
Shayan Chatterjee
quelle