2016-10-08 17:33:00 +0200, Conrad Hoffmann: [...] > $ TEST=5; echo $((--TEST+++3)) # outputs 7 > > However, due to the documented operator precedence, I would have > expected that expression to be equal to: > > $ TEST=5; echo $((--(TEST++)+3)) # outputs 8 > > Instead, though, it seems to be equal this one: > > $ TEST=5; echo $(((--TEST)+++3)) # outputs 7 > > So my qestions are: > > Is this a bug? Or is this something that can't be resolved due > ambiguities in the grammar? Or what's going on here at all? [...]
--, ++ are optional in POSIX. That means you can't use those operators in POSIX scripts and that if you need to combine two unary - or + or a binary - with a unary -, you need to use spaces or paren: $((1--1)) # unspecified $((--1)) # unspecified $((--var)) # unspecified $((1 - -1)) # OK $((- -1)) # OK $((1-(-1))) # OK $((-(-1))) # OK Now, if we look at the C spec, the way +++ is parsed is down to tokenisation that will also go for the longest operator first. There --test+++3 would be tokenised as -- test ++ + 3 which would lead to a syntax error as test++ isn't an lvalue. bash works differently. >From what I understand from past discussions on the subject here bash doesn't treat it as a syntax error and tries instead to tokenise those incorrect ++/-- into multiple + or - operators if possible. So here, --TEST+++3 is: --TEST + +(+3) And --(TEST++)+3 would be: -(-(TEST++))+3 -- Stephane