expr
scheint Klammern nicht zu mögen (wird in der Mathematik verwendet, um die Operatorpriorität zu explizieren):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
Wie drücke ich die Operatorpriorität in bash aus?
expr
scheint Klammern nicht zu mögen (wird in der Mathematik verwendet, um die Operatorpriorität zu explizieren):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
Wie drücke ich die Operatorpriorität in bash aus?
Antworten:
Eine andere Möglichkeit, let
bash builtin zu verwenden:
$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9
Hinweis
Wie @ Stéphane Chazelas betonte , bash
sollten Sie in verwenden ((...))
, um Arithmetik über expr
oder let
für die Lesbarkeit zu tun .
Für Portabilität, verwenden $((...))
wie @Bernhard Antwort .
let
. Es ist nicht standardmäßiger oder portabler als (( a = 3 * (2 + 1) ))
(beide kommen von ksh
und sind nur in ksh, bash und zsh verfügbar) und es ist weniger lesbar oder leicht zu zitieren. Gebrauch a=$((3 * (2 + 1)))
, beweglich zu sein.
((a = 3 * (2 + 1) ))
, eine für Portabilität a=$((3 * (2 + 1)))
), es ist also keine Notiz gegen Sie oder Ihre Antwort, sondern dagegen, dass es die ausgewählte Antwort ist und Torschützenkönig.
a=1 $[a+2]
oder a=1 b=2 $[a+b]
. Ist ihr Grund, diese Syntax zu vermeiden?
Sie können stattdessen die arithmetische Erweiterung verwenden.
echo "$(( 3 * ( 2 + 1 ) ))"
9
Meiner persönlichen Meinung nach sieht das ein bisschen besser aus als mit expr
.
Von man bash
Arithmetische Erweiterung Die arithmetische Erweiterung ermöglicht die Auswertung eines arithmetischen Ausdrucks und die Substitution des Ergebnisses. Das Format für die arithmetische Erweiterung lautet:
$((expression))
Der Ausdruck wird so behandelt, als befände er sich in doppelten Anführungszeichen, ein doppeltes Anführungszeichen in Klammern wird jedoch nicht speziell behandelt. Alle Token im Ausdruck werden einer Parametererweiterung, einer Zeichenfolgenerweiterung, einer Befehlssubstitution und einer Entfernung von Anführungszeichen unterzogen. Arithmetische Erweiterungen können verschachtelt sein.
Die Auswertung erfolgt nach den nachfolgend unter ARITHMETISCHE BEWERTUNG aufgeführten Regeln. Wenn der Ausdruck ungültig ist, gibt die Bash eine Meldung aus, die auf einen Fehler hinweist, und es findet keine Ersetzung statt.
Es gibt keinen Grund, expr
in modernen Schalen für das Rechnen zu verwenden.
POSIX definiert den $((...))
Expansionsoperator. Sie können das also in allen POSIX-kompatiblen Shells verwenden (die sh
aller modernen Unix-Likes, Dash, Bash, Yash, Mksh, Zsh, Posh, Ksh ...).
a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))
ksh
Außerdem wurde ein let
Builtin eingeführt, das denselben arithmetischen Ausdruck übergibt, nicht zu etwas erweitert, sondern einen Exit-Status zurückgibt, der davon abhängt, ob der Ausdruck in 0 aufgelöst wird oder nicht, wie in expr
:
if let 'a = 3 * (2 + 1)'; then
echo "$a is non-zero"
fi
Da das Zitat jedoch umständlich und nicht sehr leserlich ist (nicht im gleichen Maße wie expr
natürlich), wurde ksh
auch eine ((...))
alternative Form eingeführt:
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then
echo "$a is non-zero and 3 > 1"
fi
((a+=2))
Das ist viel besser lesbar und sollte stattdessen verwendet werden.
let
und ((...))
sind nur in ksh
, zsh
und bash
. Die $((...))
Syntax sollte bevorzugt werden, wenn die Portierbarkeit auf andere Shells erforderlich ist. Dies expr
ist nur für Bourne-ähnliche Shells vor POSIX erforderlich (normalerweise die Bourne-Shell oder frühe Versionen der Almquist-Shell).
An der Nicht-Bourne-Front gibt es einige Shells mit integriertem arithmetischen Operator:
csh
/ tcsh
(eigentlich die erste Unix-Shell mit integrierter arithmetischer Auswertung):
@ a = 3 * (2 + 1)
akanga
(basierend auf rc
)
a = $:'3 * (2 + 1)'
als geschichtsnotiz hatte die originalversion der Almquist-shell, wie sie 1989 im Usenet veröffentlicht wurde, einen expr
eingebauten (tatsächlich zusammengeführten test
), der jedoch später entfernt wurde.
: $((a = a*2))
?
$((...))
wie zsh, ksh93 oder yash unterstützt.
expr
ist ein externer Befehl, keine spezielle Shell-Syntax. Wenn Sie expr
Shell-Sonderzeichen sehen möchten , müssen Sie sie daher vor Shell-Analyse schützen, indem Sie sie in Anführungszeichen setzen. Darüber hinaus expr
muss jede Nummer und jeder Operator als separater Parameter übergeben werden. Somit:
expr 3 \* \( 2 + 1 \)
Sofern Sie nicht an einem antiken Unix-System aus den 1970er oder 1980er Jahren arbeiten, gibt es nur sehr wenige Gründe, es zu verwenden expr
. Früher hatten Shells keine eingebaute Methode zum Rechnen, und Sie mussten expr
stattdessen das Dienstprogramm aufrufen . Alle POSIX-Shells verfügen über eine integrierte Arithmetik über die arithmetische Erweiterungssyntax .
echo "$((3 * (2 + 1)))"
Das Konstrukt $((…))
expandiert zum Ergebnis des arithmetischen Ausdrucks (in Dezimalschrift geschrieben). Bash unterstützt wie die meisten Shells nur Ganzzahl-Arithmetikmodule 2 64 (oder Modulo 2 32 für ältere Versionen von Bash und einige andere Shells auf 32-Bit-Computern).
Bash bietet eine zusätzliche Komfortsyntax, wenn Sie Zuweisungen ausführen oder testen möchten, ob ein Ausdruck 0 ist, aber das Ergebnis nicht berücksichtigt. Dieses Konstrukt existiert auch in ksh und zsh, aber nicht in plain sh.
((x = 3 * (2+1)))
echo "$x"
if ((x > 3)); then …
Bietet zusätzlich zur Ganzzahlarithmetik expr
einige Funktionen zur Manipulation von Zeichenfolgen. Auch diese werden von den Funktionen der POSIX-Shells zusammengefasst, mit einer Ausnahme: expr STRING : REGEXP
Prüft, ob die Zeichenfolge mit dem angegebenen regulären Ausdruck übereinstimmt. Eine POSIX-Shell kann dies nicht ohne externe Tools tun, aber Bash kann mit [[ STRING =~ REGEXP ]]
(mit einer anderen Regexp-Syntax - expr
ist ein klassisches Tool und verwendet BRE, Bash verwendet ERE).
Sofern Sie keine Skripte verwalten, die auf 20 Jahre alten Systemen ausgeführt werden, müssen Sie nicht wissen, dass es diese expr
jemals gab. Verwenden Sie Shell-Arithmetik.
expr foo : '\(.\)'
Führt auch die Textextraktion durch. bash
's BASH_REMATCH
schafft sowas ähnliches. Es führt auch einen Zeichenfolgenvergleich durch, den POSIX [
nicht durchführt (obwohl man sich Möglichkeiten vorstellen könnte, dies zu tun sort
).
Verwenden Sie Klammern mit Anführungszeichen:
expr 3 '*' '(' 2 '+' 1 ')'
9
Die Anführungszeichen verhindern, dass Bash die Klammern als Bash-Syntax interpretiert.
expr
Befehlszeile durch Leerzeichen getrennt sein müssen. damit; zum Beispiel expr 3 "*" "(2" "+" "1)"
wird nicht funktionieren . (Übrigens müssen Sie das wahrscheinlich nicht zitieren +
.)
while
und [[
, sie sind Syntax. Wären sie Schlüsselwörter, würden sie in Befehlsargumenten nicht als solche interpretiert. Sie benötigen Anführungszeichen, damit bash sie nicht analysiert, sondern stattdessen ein Zeichenfolgenliteral anzeigt.