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 | #### SparseArray Performance demo
|
274 |
|
275 | case $SH in bash|zsh|mksh|ash) exit ;; esac
|
276 |
|
277 | #pp test_ (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 | ## STDOUT:
|
316 | SparseArray
|
317 | len: 6
|
318 | subst: foo 25 26 27 bar sparse
|
319 | keys: 0 1 2 3 4 10
|
320 | slice: 26 27 bar
|
321 | get0: set0
|
322 | get1: 25
|
323 | ---
|
324 | append
|
325 | subst: set0 25 26 27 bar sparse x y
|
326 | keys: 0 1 2 3 4 10 11 12
|
327 | ---
|
328 | unset
|
329 | subst: set0 25 26 27 bar sparse y
|
330 | keys: 0 1 2 3 4 10 12
|
331 | ## END
|
332 |
|
333 | ## N-I bash/zsh/mksh/ash STDOUT:
|
334 | ## END
|