expr
wydaje się nie lubić nawiasów (używanych w matematyce do jawnego priorytetu operatora):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
Jak wyrazić priorytet operatora w bash?
shell
quoting
arithmetic
expr
Nicolas Raoul
źródło
źródło
let
. Nie jest bardziej standardowy ani przenośny niż(( a = 3 * (2 + 1) ))
(oba pochodzą zksh
i są dostępne tylko w ksh, bash i zsh) i jest mniej czytelny lub łatwy do cytowania. Użyj,a=$((3 * (2 + 1)))
aby być przenośnym.((a = 3 * (2 + 1) ))
, jedna dla przenośnościa=$((3 * (2 + 1)))
), więc nie jest to notatka przeciwko tobie lub twojej odpowiedzi, ale przeciwko temu, że jest wybraną odpowiedzią i najlepszy strzelec.a=1 $[a+2]
luba=1 b=2 $[a+b]
. Czy ich powodem jest unikanie tej składni?Zamiast tego możesz użyć rozszerzenia arytmetycznego.
Moim osobistym zdaniem wygląda to nieco ładniej niż używanie
expr
.Od
man bash
źródło
Nie ma powodu, aby używać
expr
arytmetyki w nowoczesnych powłokach.POSIX definiuje
$((...))
operator ekspansji. Możesz więc używać tego we wszystkich powłokach zgodnych z POSIX (sh
wszystkich współczesnych uniksowych lajków, dash, bash, yash, mksh, zsh, posh, ksh ...).ksh
wprowadzono równieżlet
wbudowane, które jest przekazywane tego samego rodzaju wyrażenie arytmetyczne, nie rozwija się w coś, ale zwraca status wyjścia na podstawie tego, czy wyrażenie jest interpretowane na 0, czy nie, jak wexpr
:Ponieważ jednak cytowanie sprawia, że jest to niewygodne i mało czytelne (nie w takim samym stopniu jak
expr
oczywiście),ksh
wprowadzono także((...))
alternatywną formę:który jest o wiele bardziej czytelny i powinien być używany zamiast tego.
let
i((...))
są dostępne tylko wksh
,zsh
ibash
.$((...))
Składni powinny być korzystna, jeśli potrzebny do przenoszenia innych powłok,expr
potrzebne jest tylko do wstępnego POSIX Bourne powłokach (zazwyczaj Bourne powłoki lub wczesne wersje Almquist Shell).Na froncie innym niż Bourne znajduje się kilka pocisków z wbudowanym operatorem arytmetycznym:
csh
/tcsh
(właściwie pierwsza powłoka uniksowa z wbudowaną analizą arytmetyczną):akanga
(na podstawierc
)jak napisano w historii, oryginalna wersja powłoki Almquist, opublikowana na usenet w 1989 roku, miała
expr
wbudowaną (faktycznie połączonątest
), ale została później usunięta.źródło
: $((a = a*2))
?$((...))
takie jak zsh, ksh93 lub yash.expr
jest poleceniem zewnętrznym, nie jest specjalną składnią powłoki. Dlatego jeśli chceszexpr
zobaczyć znaki specjalne powłoki, musisz chronić je przed analizą powłoki, cytując je. Ponadtoexpr
wymaga podania każdej liczby i operatora jako osobnego parametru. A zatem:O ile nie pracujesz na antycznym systemie uniksowym z lat 70. lub 80. XX wieku, nie ma zbyt wiele powodów, aby z niego korzystać
expr
. W dawnych czasach powłoki nie miały wbudowanego sposobu wykonywania arytmetyki, aexpr
zamiast tego trzeba było wywołać narzędzie. Wszystkie powłoki POSIX mają wbudowaną arytmetykę poprzez arytmetyczną składnię rozszerzającą .Konstrukt
$((…))
rozwija się do wyniku wyrażenia arytmetycznego (zapisanego dziesiętnie). Bash, podobnie jak większość powłok, obsługuje tylko liczbę całkowitą arytmetyczną modulo 2 64 (lub modulo 2 32 dla starszych wersji basha i niektórych innych powłok na maszynach 32-bitowych).Bash oferuje dodatkową wygodną składnię, gdy chcesz wykonać przypisania lub sprawdzić, czy wyrażenie ma wartość 0, ale nie przejmuj się wynikiem. Ta konstrukcja istnieje również w ksh i zsh, ale nie w zwykłym sh.
Oprócz arytmetyki liczb całkowitych
expr
oferuje kilka funkcji manipulacji ciągami. Te także są uwzględniane przez funkcje powłok POSIX, z wyjątkiem jednego:expr STRING : REGEXP
testuje, czy łańcuch pasuje do określonego wyrażenia regularnego. Powłoka POSIX nie może tego zrobić bez zewnętrznych narzędzi, ale bash może[[ STRING =~ REGEXP ]]
(z inną składnią wyrażenia regularnego -expr
jest klasycznym narzędziem i używa BRE, bash używa ERE).O ile nie zajmujesz się skryptami działającymi na 20-letnich systemach, nie musisz wiedzieć, że
expr
kiedykolwiek istniał. Użyj arytmetyki powłoki.źródło
expr foo : '\(.\)'
wykonuje również ekstrakcję tekstu.bash
„sBASH_REMATCH
osiąga coś podobnego. Dokonuje również porównania ciągów, czego[
nie robi POSIX (choć można sobie wyobrazić, jak tego użyćsort
).Używaj nawiasów z cytatami:
Cytaty uniemożliwiają bashowi zinterpretowanie nawiasu jako składni bash.
źródło
expr
wierszu poleceń muszą być oddzielone spacjami; więc; na przykładexpr 3 "*" "(2" "+" "1)"
nie będzie działać . (Ponadto, BTW, prawdopodobnie nie musisz cytować+
.)while
i[[
są składnią. Gdyby były słowami kluczowymi, nie byłyby interpretowane jako takie w argumentach poleceń. Potrzebujesz cudzysłowów, aby bash ich nie analizował, a zamiast tego widział dosłowny ciąg znaków.Jeśli masz Bc ..
źródło