1
2 #### recursive arith: one level
3 a='b=123'
4 echo $((a))
5 ## stdout: 123
6 ## N-I dash status: 2
7 ## N-I dash stdout-json: ""
8 ## N-I yash stdout: b=123
9
10 #### recursive arith: two levels
11 a='b=c' c='d=123'
12 echo $((a))
13 ## stdout: 123
14 ## N-I dash status: 2
15 ## N-I dash stdout-json: ""
16 ## N-I yash stdout: b=c
17
18 #### recursive arith: short circuit &&, ||
19 # Note: mksh R52 has a bug. Even though it supports a short circuit like
20 # "echo $((cond&&(a=1)))", it doesn't work with "x=a=1; echo
21 # $((cond&&x))". It is fixed at least in mksh R57.
22 # Note: "busybox sh" doesn't support short circuit.
23 a=b=123
24 echo $((1||a)):$((b))
25 echo $((0||a)):$((b))
26 c=d=321
27 echo $((0&&c)):$((d))
28 echo $((1&&c)):$((d))
29 ## STDOUT:
30 1:0
31 1:123
32 0:0
33 1:321
34 ## END
35
36 ## BUG mksh/ash STDOUT:
37 1:123
38 1:123
39 0:321
40 1:321
41 ## END
42
43 ## N-I dash/yash status: 2
44 ## N-I dash/yash STDOUT:
45 1:0
46 ## END
47
48 #### recursive arith: short circuit ?:
49 # Note: "busybox sh" behaves strangely.
50 y=a=123 n=a=321
51 echo $((1?(y):(n))):$((a))
52 echo $((0?(y):(n))):$((a))
53 ## STDOUT:
54 123:123
55 321:321
56 ## END
57 ## BUG ash STDOUT:
58 123:321
59 321:321
60 ## END
61 ## N-I dash status: 2
62 ## N-I dash stdout-json: ""
63 ## N-I yash STDOUT:
64 a=123:0
65 a=321:0
66 ## END
67
68 #### recursive arith: side effects
69 # In Zsh and Busybox sh, the side effect of inner arithmetic
70 # evaluations seems to take effect only after the whole evaluation.
71 a='b=c' c='d=123'
72 echo $((a,d)):$((d))
73 ## stdout: 123:123
74 ## BUG zsh/ash stdout: 0:123
75 ## N-I dash/yash status: 2
76 ## N-I dash/yash stdout-json: ""
77
78 #### recursive arith: recursion
79 loop='i<=100&&(s+=i,i++,loop)' s=0 i=0
80 echo $((a=loop,s))
81 ## stdout: 5050
82 ## N-I mksh status: 1
83 ## N-I mksh stdout-json: ""
84 ## N-I ash/dash/yash status: 2
85 ## N-I ash/dash/yash stdout-json: ""
86
87 #### recursive arith: array elements
88 text[1]='d=123'
89 text[2]='text[1]'
90 text[3]='text[2]'
91 echo $((a=text[3]))
92 ## stdout: 123
93 ## N-I ash/dash/yash status: 2
94 ## N-I ash/dash/yash stdout-json: ""
95
96 #### dynamic arith varname: assign
97 vec2_set () {
98 local this=$1 x=$2 y=$3
99 : $(( ${this}_x = $2 ))
100 : $(( ${this}_y = y ))
101 }
102 vec2_set a 3 4
103 vec2_set b 5 12
104 echo a_x=$a_x a_y=$a_y
105 echo b_x=$b_x b_y=$b_y
106 ## STDOUT:
107 a_x=3 a_y=4
108 b_x=5 b_y=12
109 ## END
110
111 #### dynamic arith varname: read
112
113 vec2_load() {
114 local this=$1
115 x=$(( ${this}_x ))
116 : $(( y = ${this}_y ))
117 }
118 a_x=12 a_y=34
119 vec2_load a
120 echo x=$x y=$y
121 ## STDOUT:
122 x=12 y=34
123 ## END
124
125 #### dynamic arith varname: copy/add
126 shopt -s eval_unsafe_arith # for RHS
127
128 vec2_copy () {
129 local this=$1 rhs=$2
130 : $(( ${this}_x = $(( ${rhs}_x )) ))
131 : $(( ${this}_y = ${rhs}_y ))
132 }
133 vec2_add () {
134 local this=$1 rhs=$2
135 : $(( ${this}_x += $(( ${rhs}_x )) ))
136 : $(( ${this}_y += ${rhs}_y ))
137 }
138 a_x=3 a_y=4
139 b_x=4 b_y=20
140 vec2_copy c a
141 echo c_x=$c_x c_y=$c_y
142 vec2_add c b
143 echo c_x=$c_x c_y=$c_y
144 ## STDOUT:
145 c_x=3 c_y=4
146 c_x=7 c_y=24
147 ## END
148
149 #### is-array with ${var@a}
150 case $SH in (mksh|ash|dash|yash) exit 1 ;; esac
151
152 function ble/is-array { [[ ${!1@a} == *a* ]]; }
153
154 ble/is-array undef
155 echo undef $?
156
157 string=''
158 ble/is-array string
159 echo string $?
160
161 array=(one two three)
162 ble/is-array array
163 echo array $?
164 ## STDOUT:
165 undef 1
166 string 1
167 array 0
168 ## END
169 ## N-I zsh/mksh/ash/dash/yash status: 1
170 ## N-I zsh/mksh/ash/dash/yash stdout-json: ""
171
172
173 #### Sparse array with big index
174
175 # TODO: more BashArray idioms / stress tests ?
176
177 a=()
178
179 if false; then
180 # This takes too long! # From Zulip
181 i=$(( 0x0100000000000000 ))
182 else
183 # smaller number that's OK
184 i=$(( 0x0100000 ))
185 fi
186
187 a[i]=1
188
189 echo len=${#a[@]}
190
191 ## STDOUT:
192 len=1
193 ## END
194
195 ## N-I ash status: 2
196 ## N-I ash STDOUT:
197 ## END
198
199 ## BUG zsh STDOUT:
200 len=1048576
201 ## END
202
203
204 #### shift unshift reverse
205
206 case $SH in mksh|ash) exit ;; esac
207
208 # https://github.com/akinomyoga/ble.sh/blob/79beebd928cf9f6506a687d395fd450d027dc4cd/src/util.sh#L578-L582
209
210 # @fn ble/array#unshift arr value...
211 function ble/array#unshift {
212 builtin eval -- "$1=(\"\${@:2}\" \"\${$1[@]}\")"
213 }
214 # @fn ble/array#shift arr count
215 function ble/array#shift {
216 # Note: Bash 4.3 以下では ${arr[@]:${2:-1}} が offset='${2'
217 # length='-1' に解釈されるので、先に算術式展開させる。
218 builtin eval -- "$1=(\"\${$1[@]:$((${2:-1}))}\")"
219 }
220 # @fn ble/array#reverse arr
221 function ble/array#reverse {
222 builtin eval "
223 set -- \"\${$1[@]}\"; $1=()
224 local e$1 i$1=\$#
225 for e$1; do $1[--i$1]=\"\$e$1\"; done"
226 }
227
228 a=( {1..6} )
229 echo "${a[@]}"
230
231 ble/array#shift a 1
232 echo "${a[@]}"
233
234 ble/array#shift a 2
235 echo "${a[@]}"
236
237 echo ---
238
239 ble/array#unshift a 99
240 echo "${a[@]}"
241
242 echo ---
243
244 # doesn't work in zsh!
245 ble/array#reverse a
246 echo "${a[@]}"
247
248
249 ## STDOUT:
250 1 2 3 4 5 6
251 2 3 4 5 6
252 4 5 6
253 ---
254 99 4 5 6
255 ---
256 6 5 4 99
257 ## END
258
259 ## BUG zsh STDOUT:
260 1 2 3 4 5 6
261 2 3 4 5 6
262 4 5 6
263 ---
264 99 4 5 6
265 ---
266 5 4 99
267 ## END
268
269 ## N-I mksh/ash STDOUT:
270 ## END
271
272
273 #### Performance demo
274
275 case $SH in bash|zsh|mksh|ash) exit ;; esac
276
277 #pp line (a)
278
279 a=( foo {25..27} bar )
280
281 a[10]='sparse'
282
283 var sp = _a2sp(a)
284 echo $[type(sp)]
285
286 echo len: $[_opsp(sp, 'len')]
287
288 #echo $[len(sp)]
289
290 shopt -s ysh:upgrade
291
292 echo subst: @[_opsp(sp, 'subst')]
293 echo keys: @[_opsp(sp, 'keys')]
294
295 echo slice: @[_opsp(sp, 'slice', 2, 5)]
296
297 call _opsp(sp, 'set', 0, 'set0')
298
299 echo get0: $[_opsp(sp, 'get', 0)]
300 echo get1: $[_opsp(sp, 'get', 1)]
301 echo ---
302
303 to_append=(x y)
304 echo append
305 call _opsp(sp, 'append', to_append)
306 echo subst: @[_opsp(sp, 'subst')]
307 echo keys: @[_opsp(sp, 'keys')]
308 echo ---
309
310 echo unset
311 call _opsp(sp, 'unset', 11)
312 echo subst: @[_opsp(sp, 'subst')]
313 echo keys: @[_opsp(sp, 'keys')]
314
315 echo ---
316
317 # Sparse
318 var d = {
319 '1': 'a',
320 '10': 'b',
321 '100': 'c',
322 '1000': 'd',
323 '10000': 'e',
324 '100000': 'f',
325 }
326
327 var sp2 = _d2sp(d)
328
329 echo len: $[_opsp(sp2, 'len')]
330 echo subst: @[_opsp(sp2, 'subst')]
331
332
333 ## STDOUT:
334 SparseArray
335 len: 6
336 subst: foo 25 26 27 bar sparse
337 keys: 0 1 2 3 4 10
338 slice: 26 27 bar
339 get0: set0
340 get1: 25
341 ---
342 append
343 subst: set0 25 26 27 bar sparse x y
344 keys: 0 1 2 3 4 10 11 12
345 ---
346 unset
347 subst: set0 25 26 27 bar sparse y
348 keys: 0 1 2 3 4 10 12
349 ---
350 len: 6
351 subst: a b c d e f
352 ## END
353
354 ## N-I bash/zsh/mksh/ash STDOUT:
355 ## END