1 ## compare_shells: bash-4.4 mksh zsh
2
3 #### (( )) result
4 (( 1 )) && echo True
5 (( 0 )) || echo False
6 ## stdout-json: "True\nFalse\n"
7
8 #### negative number is true
9 (( -1 )) && echo True
10 ## stdout: True
11
12 #### (( )) in if statement
13 if (( 3 > 2)); then
14 echo True
15 fi
16 ## stdout: True
17
18 #### (( ))
19 # What is the difference with this and let? One difference: spaces are allowed.
20 (( x = 1 ))
21 (( y = x + 2 ))
22 echo $x $y
23 ## stdout: 1 3
24
25 #### (( )) with arrays
26 a=(4 5 6)
27 (( sum = a[0] + a[1] + a[2] ))
28 echo $sum
29 ## stdout: 15
30 ## OK zsh stdout: 9
31
32 #### (( )) with error
33 (( a = 0 )) || echo false
34 (( b = 1 )) && echo true
35 (( c = -1 )) && echo true
36 echo $((a + b + c))
37 ## STDOUT:
38 false
39 true
40 true
41 0
42 ## END
43
44
45 #### bash and mksh: V in (( a[K] = V )) gets coerced to integer
46 shopt -u strict_arith || true
47 K=key
48 V=value
49 typeset -a a
50 (( a[K] = V ))
51
52 # not there!
53 echo a[\"key\"]=${a[$K]}
54
55 echo keys = ${!a[@]}
56 echo values = ${a[@]}
57 ## STDOUT:
58 a["key"]=0
59 keys = 0
60 values = 0
61 ## END
62 ## N-I zsh status: 1
63 ## N-I zsh stdout-json: ""
64
65 #### bash: K in (( A[K] = V )) is a constant string
66 K=5
67 V=42
68 typeset -A A
69 (( A[K] = V ))
70
71 echo A["5"]=${A["5"]}
72 echo keys = ${!A[@]}
73 echo values = ${A[@]}
74 ## STDOUT:
75 A[5]=
76 keys = K
77 values = 42
78 ## END
79 ## OK osh status: 1
80 ## OK osh stdout-json: ""
81 ## N-I zsh status: 1
82 ## N-I zsh stdout-json: ""
83 ## N-I mksh status: 1
84 ## N-I mksh stdout-json: ""
85
86 #### BUG: (( V = A[K] )) doesn't retrieve the right value
87 typeset -A A
88 K=5
89 V=42
90 A["$K"]=$V
91 A["K"]=oops
92 A[K]=oops2
93
94 # We don't neither 42 nor "oops". Bad!
95 (( V = A[K] ))
96
97 echo V=$V
98 ## status: 1
99 ## stdout-json: ""
100 ## BUG bash/zsh status: 0
101 ## BUG bash/zsh STDOUT:
102 V=0
103 ## END
104
105 #### bash: V in (( A["K"] = V )) gets coerced to integer
106 shopt -u strict_arith || true
107 K=key
108 V=value
109 typeset -A A || exit 1
110 (( A["K"] = V ))
111
112 # not there!
113 echo A[\"key\"]=${A[$K]}
114
115 echo keys = ${!A[@]}
116 echo values = ${A[@]}
117 ## STDOUT:
118 A["key"]=
119 keys = K
120 values = 0
121 ## END
122 ## N-I zsh stdout-json: ""
123 ## N-I zsh status: 1
124 ## N-I mksh stdout-json: ""
125 ## N-I mksh status: 1
126
127 #### literal strings inside (( ))
128 declare -A A
129 A['x']=42
130 (( x = A['x'] ))
131 (( A['y'] = 'y' )) # y is a variable, gets coerced to 0
132 echo $x ${A['y']}
133 ## STDOUT:
134 42 0
135 ## END
136 ## BUG mksh status: 0
137 ## N-I mksh STDOUT:
138 0
139 ## END
140 ## BUG zsh status: 0
141 ## N-I zsh STDOUT:
142 42
143 ## END
144
145 #### (( )) with redirect
146 (( a = $(stdout_stderr.py 42) + 10 )) 2>$TMP/x.txt
147 echo $a
148 echo --
149 cat $TMP/x.txt
150 ## STDOUT:
151 52
152 --
153 STDERR
154 ## END
155
156 #### Assigning whole raray (( b = a ))
157 a=(4 5 6)
158 (( b = a ))
159
160 echo "${a[@]}"
161
162 # OSH doesn't like this
163 echo "${b[@]}"
164
165 ## status: 0
166 ## STDOUT:
167 4 5 6
168 4
169 ## END
170 ## BUG zsh status: 0
171 ## BUG zsh STDOUT:
172 4 5 6
173
174 ## END
175
176 #### set associative array
177 declare -A A=(['foo']=bar ['spam']=42)
178 (( x = A['spam'] ))
179 echo $x
180 ## STDOUT:
181 42
182 ## END
183 ## N-I mksh status: 1
184 ## N-I mksh stdout-json: ""
185 ## N-I zsh STDOUT:
186 0
187 ## END
188
189 #### Example of incrementing associative array entry with var key (ble.sh)
190 declare -A A=(['foo']=42)
191 key='foo'
192
193 # note: in bash, (( A[\$key] += 1 )) works the same way.
194
195 set -- 1 2
196 (( A[$key] += $2 ))
197
198 echo foo=${A['foo']}
199
200 ## STDOUT:
201 foo=44
202 ## END
203 ## N-I mksh/zsh status: 1
204 ## N-I mksh/zsh stdout-json: ""
205