1 ## compare_shells: bash mksh
2 ## oils_failures_allowed: 2
3
4 #### nounset / set -u with empty array (bug in bash 4.3, fixed in 4.4)
5
6 # http://lists.gnu.org/archive/html/help-bash/2017-09/msg00005.html
7
8 set -o nounset
9 empty=()
10 argv.py "${empty[@]}"
11 echo status=$?
12 ## STDOUT:
13 []
14 status=0
15 ## END
16 ## BUG mksh stdout-json: ""
17 ## BUG mksh status: 1
18
19 #### local array
20 # mksh support local variables, but not local arrays, oddly.
21 f() {
22 local a=(1 '2 3')
23 argv.py "${a[0]}"
24 }
25 f
26 ## stdout: ['1']
27 ## status: 0
28 ## BUG mksh status: 1
29 ## BUG mksh stdout-json: ""
30
31 #### Command with with word splitting in array
32 array=('1 2' $(echo '3 4'))
33 argv.py "${array[@]}"
34 ## stdout: ['1 2', '3', '4']
35
36 #### space before ( in array initialization
37 # NOTE: mksh accepts this, but bash doesn't
38 a= (1 '2 3')
39 echo $a
40 ## status: 2
41 ## OK mksh status: 0
42 ## OK mksh stdout: 1
43
44 #### array over multiple lines
45 a=(
46 1
47 '2 3'
48 )
49 argv.py "${a[@]}"
50 ## stdout: ['1', '2 3']
51 ## status: 0
52
53 #### array with invalid token
54 a=(
55 1
56 &
57 '2 3'
58 )
59 argv.py "${a[@]}"
60 ## status: 2
61 ## OK mksh status: 1
62
63 #### array with empty string
64 empty=('')
65 argv.py "${empty[@]}"
66 ## stdout: ['']
67
68 #### Retrieve index
69 a=(1 '2 3')
70 argv.py "${a[1]}"
71 ## stdout: ['2 3']
72
73 #### Retrieve out of bounds index
74 a=(1 '2 3')
75 argv.py "${a[3]}"
76 ## stdout: ['']
77
78 #### Negative index
79 a=(1 '2 3')
80 argv.py "${a[-1]}" "${a[-2]}" "${a[-5]}" # last one out of bounds
81 ## stdout: ['2 3', '1', '']
82 ## N-I mksh stdout: ['', '', '']
83
84 #### Negative index and sparse array
85 a=(0 1 2 3 4)
86 unset a[1]
87 unset a[4]
88 echo "${a[@]}"
89 echo -1 ${a[-1]}
90 echo -2 ${a[-2]}
91 echo -3 ${a[-3]}
92 echo -4 ${a[-4]}
93 echo -5 ${a[-5]}
94
95 a[-1]+=0 # append 0 on the end
96 echo ${a[@]}
97 (( a[-1] += 42 ))
98 echo ${a[@]}
99
100 ## STDOUT:
101 0 2 3
102 -1 3
103 -2 2
104 -3
105 -4 0
106 -5
107 0 2 30
108 0 2 72
109 ## END
110 ## BUG mksh STDOUT:
111 0 2 3
112 -1
113 -2
114 -3
115 -4
116 -5
117 0 2 3 0
118 0 2 3 42
119 ## END
120
121 #### Negative index and sparse array
122 a=(0 1)
123 unset 'a[-1]' # remove last element
124 a+=(2 3)
125 echo ${a[0]} $((a[0]))
126 echo ${a[1]} $((a[1]))
127 echo ${a[2]} $((a[2]))
128 echo ${a[3]} $((a[3]))
129 ## STDOUT:
130 0 0
131 2 2
132 3 3
133 0
134 ## END
135 ## BUG mksh STDOUT:
136 0 0
137 1 1
138 2 2
139 3 3
140 ## END
141
142 #### Length after unset
143 a=(0 1 2 3)
144 unset a[-1]
145 echo len=${#a[@]}
146 unset a[-1]
147 echo len=${#a[@]}
148 ## STDOUT:
149 len=3
150 len=2
151 ## END
152 ## BUG mksh STDOUT:
153 len=4
154 len=4
155 ## END
156
157 #### Retrieve index that is a variable
158 a=(1 '2 3')
159 i=1
160 argv.py "${a[$i]}"
161 ## stdout: ['2 3']
162
163 #### Retrieve index that is a variable without $
164 a=(1 '2 3')
165 i=5
166 argv.py "${a[i-4]}"
167 ## stdout: ['2 3']
168
169 #### Retrieve index that is a command sub
170 a=(1 '2 3')
171 argv.py "${a[$(echo 1)]}"
172 ## stdout: ['2 3']
173
174 #### Retrieve array indices with ${!a}
175 a=(1 '2 3')
176 argv.py "${!a[@]}"
177 ## stdout: ['0', '1']
178
179 #### Retrieve sparse array indices with ${!a}
180 a=()
181 (( a[99]=1 ))
182 argv.py "${!a[@]}"
183 ## STDOUT:
184 ['99']
185 ## END
186
187 #### ${!a[1]} is named ref in bash
188 # mksh ignores it
189 foo=bar
190 a=('1 2' foo '2 3')
191 argv.py "${!a[1]}"
192 ## status: 0
193 ## stdout: ['bar']
194 ## N-I mksh stdout: ['a[1]']
195
196 #### ${!a} on array
197
198 # bash gives empty string because it's like a[0]
199 # mksh gives the name of the variable with !. Very weird.
200
201 a=(1 '2 3')
202 argv.py "${!a}"
203
204 ## stdout: ['']
205 ## status: 0
206 ## BUG mksh stdout: ['a']
207 ## BUG mksh status: 0
208
209 #### All elements unquoted
210 a=(1 '2 3')
211 argv.py ${a[@]}
212 ## stdout: ['1', '2', '3']
213
214 #### All elements quoted
215 a=(1 '2 3')
216 argv.py "${a[@]}"
217 ## stdout: ['1', '2 3']
218
219 #### $*
220 a=(1 '2 3')
221 argv.py ${a[*]}
222 ## stdout: ['1', '2', '3']
223
224 #### "$*"
225 a=(1 '2 3')
226 argv.py "${a[*]}"
227 ## stdout: ['1 2 3']
228
229 #### Interpolate array into array
230 a=(1 '2 3')
231 a=(0 "${a[@]}" '4 5')
232 argv.py "${a[@]}"
233 ## stdout: ['0', '1', '2 3', '4 5']
234
235 #### Exporting array doesn't do anything, not even first element
236 # bash parses, but doesn't execute.
237 # mksh gives syntax error -- parses differently with 'export'
238 # osh no longer parses this statically.
239
240 export PYTHONPATH
241
242 PYTHONPATH=mystr # NOTE: in bash, this doesn't work afterward!
243 printenv.py PYTHONPATH
244
245 PYTHONPATH=(myarray)
246 printenv.py PYTHONPATH
247
248 PYTHONPATH=(a b c)
249 printenv.py PYTHONPATH
250
251 ## status: 0
252 ## STDOUT:
253 mystr
254 None
255 None
256 ## END
257
258 #### strict_array prevents exporting array
259
260 shopt -s strict_array
261
262 export PYTHONPATH
263 PYTHONPATH=(a b c)
264 printenv.py PYTHONPATH
265
266 ## status: 1
267 ## STDOUT:
268 ## END
269
270 ## N-I bash/mksh status: 0
271 ## N-I bash/mksh STDOUT:
272 None
273 ## END
274
275 #### Arrays can't be used as env bindings
276 # Hm bash it treats it as a string!
277 A=a B=(b b) printenv.py A B
278 ## status: 2
279 ## stdout-json: ""
280 ## OK bash stdout-json: "a\n(b b)\n"
281 ## OK bash status: 0
282 ## OK mksh status: 1
283
284 #### Set element
285 a=(1 '2 3')
286 a[0]=9
287 argv.py "${a[@]}"
288 ## stdout: ['9', '2 3']
289
290 #### Set element with var ref
291 a=(1 '2 3')
292 i=0
293 a[$i]=9
294 argv.py "${a[@]}"
295 ## stdout: ['9', '2 3']
296
297 #### Set element with array ref
298 # This makes parsing a little more complex. Anything can be inside [],
299 # including other [].
300 a=(1 '2 3')
301 i=(0 1)
302 a[${i[1]}]=9
303 argv.py "${a[@]}"
304 ## stdout: ['1', '9']
305
306 #### Set array item to array
307 a=(1 2)
308 a[0]=(3 4)
309 echo "status=$?"
310 ## stdout-json: ""
311 ## status: 2
312 ## N-I mksh status: 1
313 ## BUG bash stdout: status=1
314 ## BUG bash status: 0
315
316 #### Slice of array with [@]
317 # mksh doesn't support this syntax! It's a bash extension.
318 a=(1 2 3)
319 argv.py "${a[@]:1:2}"
320 ## stdout: ['2', '3']
321 ## N-I mksh status: 1
322 ## N-I mksh stdout-json: ""
323
324 #### Negative slice begin
325 # mksh doesn't support this syntax! It's a bash extension.
326 # NOTE: for some reason -2) has to be in parens? Ah that's because it
327 # conflicts with :-! That's silly. You can also add a space.
328 a=(1 2 3 4 5)
329 argv.py "${a[@]:(-4)}"
330 ## stdout: ['2', '3', '4', '5']
331 ## N-I mksh status: 1
332 ## N-I mksh stdout-json: ""
333
334 #### Negative slice length
335 a=(1 2 3 4 5)
336 argv.py "${a[@]: 1: -3}"
337 ## status: 1
338 ## stdout-json: ""
339
340 #### Slice with arithmetic
341 a=(1 2 3)
342 i=5
343 argv.py "${a[@]:i-4:2}"
344 ## stdout: ['2', '3']
345 ## N-I mksh status: 1
346 ## N-I mksh stdout-json: ""
347
348 #### Number of elements
349 a=(1 '2 3')
350 echo "${#a[@]}" ${#a[@]} # bug fix: also test without quotes
351 ## stdout: 2 2
352
353 #### Length of an element
354 a=(1 '2 3')
355 echo "${#a[1]}"
356 ## stdout: 3
357
358 #### Iteration
359 a=(1 '2 3')
360 for v in "${a[@]}"; do
361 echo $v
362 done
363 ## stdout-json: "1\n2 3\n"
364
365 #### glob within array yields separate elements
366 touch _tmp/y.Y _tmp/yy.Y
367 a=(_tmp/*.Y)
368 argv.py "${a[@]}"
369 ## stdout: ['_tmp/y.Y', '_tmp/yy.Y']
370
371 #### declare array and then append
372 declare -a array
373 array+=(a)
374 array+=(b c)
375 argv.py "${array[@]}"
376 ## stdout: ['a', 'b', 'c']
377
378 #### Array syntax in wrong place
379 ls foo=(1 2)
380 ## status: 1
381 ## OK bash status: 2
382
383 #### Single array with :-
384
385 # 2024-06 - bash 5.2 and mksh now match, bash 4.4 differed.
386 # Could change OSH
387 # zsh agrees with OSH, but it fails most test cases
388 # 2025-01 We changed OSH.
389
390 single=('')
391 argv.py ${single[@]:-none} x "${single[@]:-none}"
392 ## stdout: ['none', 'x', 'none']
393
394 #### Stripping a whole array unquoted
395 # Problem: it joins it first.
396 files=('foo.c' 'sp ace.h' 'bar.c')
397 argv.py ${files[@]%.c}
398 ## status: 0
399 ## stdout: ['foo', 'sp', 'ace.h', 'bar']
400 ## N-I mksh status: 1
401 ## N-I mksh stdout-json: ""
402
403 #### Stripping a whole array quoted
404 files=('foo.c' 'sp ace.h' 'bar.c')
405 argv.py "${files[@]%.c}"
406 ## status: 0
407 ## stdout: ['foo', 'sp ace.h', 'bar']
408 ## N-I mksh status: 1
409 ## N-I mksh stdout-json: ""
410
411 #### Multiple subscripts not allowed
412 # NOTE: bash 4.3 had a bug where it ignored the bad subscript, but now it is
413 # fixed.
414 a=('123' '456')
415 argv.py "${a[0]}" "${a[0][0]}"
416 ## stdout-json: ""
417 ## status: 2
418 ## OK bash/mksh status: 1
419
420 #### Length op, index op, then transform op is not allowed
421 a=('123' '456')
422 echo "${#a[0]}" "${#a[0]/1/xxx}"
423 ## stdout-json: ""
424 ## status: 2
425 ## OK bash/mksh status: 1
426
427 #### ${mystr[@]} and ${mystr[*]} are no-ops
428 s='abc'
429 echo ${s[@]}
430 echo ${s[*]}
431 ## STDOUT:
432 abc
433 abc
434 ## END
435
436 #### ${mystr[@]} and ${mystr[*]} disallowed with strict_array
437
438 $SH -c 'shopt -s strict_array; s="abc"; echo ${s[@]}'
439 echo status=$?
440
441 $SH -c 'shopt -s strict_array; s="abc"; echo ${s[*]}'
442 echo status=$?
443
444 ## status: 0
445 ## STDOUT:
446 status=1
447 status=1
448 ## END
449 ## N-I bash/mksh STDOUT:
450 abc
451 status=0
452 abc
453 status=0
454 ## END
455
456 #### Create a "user" array out of the argv array
457 set -- 'a b' 'c'
458 array1=('x y' 'z')
459 array2=("$@")
460 argv.py "${array1[@]}" "${array2[@]}"
461 ## stdout: ['x y', 'z', 'a b', 'c']
462
463 #### Tilde expansion within array
464 HOME=/home/bob
465 a=(~/src ~/git)
466 echo "${a[@]}"
467 ## stdout: /home/bob/src /home/bob/git
468
469 #### Brace Expansion within Array
470 a=(-{a,b} {c,d}-)
471 echo "${a[@]}"
472 ## stdout: -a -b c- d-
473
474 #### array default
475 default=('1 2' '3')
476 argv.py "${undef[@]:-${default[@]}}"
477 ## stdout: ['1 2', '3']
478
479 #### Singleton Array Copy and Assign. OSH can't index strings with ints
480 a=( '12 3' )
481 b=( "${a[@]}" )
482 c="${a[@]}" # This decays it to a string
483 d=${a[*]} # This decays it to a string
484 echo ${#a[0]} ${#b[0]}
485 echo ${#a[@]} ${#b[@]}
486
487 # osh is intentionally stricter, and these fail.
488 echo ${#c[0]} ${#d[0]}
489 echo ${#c[@]} ${#d[@]}
490
491 ## status: 1
492 ## STDOUT:
493 4 4
494 1 1
495 ## END
496 ## OK bash/mksh status: 0
497 ## OK bash/mksh STDOUT:
498 4 4
499 1 1
500 4 4
501 1 1
502 ## END
503
504 #### declare -a / local -a is empty array
505 declare -a myarray
506 argv.py "${myarray[@]}"
507 myarray+=('x')
508 argv.py "${myarray[@]}"
509
510 f() {
511 local -a myarray
512 argv.py "${myarray[@]}"
513 myarray+=('x')
514 argv.py "${myarray[@]}"
515 }
516 f
517 ## STDOUT:
518 []
519 ['x']
520 []
521 ['x']
522 ## END
523
524 #### Create sparse array
525 a=()
526 (( a[99]=1 )) # osh doesn't parse index assignment outside arithmetic yet
527 echo len=${#a[@]}
528 argv.py "${a[@]}"
529 echo "unset=${a[33]}"
530 echo len-of-unset=${#a[33]}
531 ## STDOUT:
532 len=1
533 ['1']
534 unset=
535 len-of-unset=0
536 ## END
537
538 #### Create sparse array implicitly
539 (( a[99]=1 ))
540 echo len=${#a[@]}
541 argv.py "${a[@]}"
542 echo "unset=${a[33]}"
543 echo len-of-unset=${#a[33]}
544 ## STDOUT:
545 len=1
546 ['1']
547 unset=
548 len-of-unset=0
549 ## END
550
551 #### Append sparse arrays
552 a=()
553 (( a[99]=1 ))
554 b=()
555 (( b[33]=2 ))
556 (( b[66]=3 ))
557 a+=( "${b[@]}" )
558 argv.py "${a[@]}"
559 argv.py "${a[99]}" "${a[100]}" "${a[101]}"
560 ## STDOUT:
561 ['1', '2', '3']
562 ['1', '2', '3']
563 ## END
564
565 #### Slice of sparse array with [@]
566 # mksh doesn't support this syntax! It's a bash extension.
567 (( a[33]=1 ))
568 (( a[66]=2 ))
569 (( a[99]=2 ))
570 argv.py "${a[@]:15:2}"
571 ## stdout: ['1', '2']
572 ## N-I mksh status: 1
573 ## N-I mksh stdout-json: ""
574
575 #### Using an array itself as the index on LHS
576 shopt -u strict_arith
577 a[a]=42
578 a[a]=99
579 argv.py "${a[@]}" "${a[0]}" "${a[42]}" "${a[99]}"
580
581 ## status: 0
582 ## STDOUT:
583 ['42', '99', '42', '99', '']
584 ## END
585
586 #### Using an array itself as the index on RHS
587 shopt -u strict_arith
588 a=(1 2 3)
589 (( x = a[a] ))
590 echo $x
591 ## status: 0
592 ## STDOUT:
593 2
594 ## END
595
596 #### a[$x$y] on LHS and RHS
597 x=1
598 y=2
599 a[$x$y]=foo
600
601 # not allowed by OSH parsing
602 #echo ${a[$x$y]}
603
604 echo ${a[12]}
605 echo ${#a[@]}
606
607 ## STDOUT:
608 foo
609 1
610 ## END
611
612
613 #### Dynamic parsing of LHS a[$code]=value
614
615 declare -a array
616 array[x=1]='one'
617
618 code='y=2'
619 #code='1+2' # doesn't work either
620 array[$code]='two'
621
622 argv.py "${array[@]}"
623 echo x=$x
624 echo y=$y
625
626 ## STDOUT:
627 ['one', 'two']
628 x=1
629 y=2
630 ## END
631 ## N-I dash stdout-json: ""
632 ## N-I dash status: 2
633
634 #### Dynamic parsing of RHS ${a[$code]}
635 declare -a array
636 array=(zero one two three)
637
638 echo ${array[1+2]}
639
640 code='1+2'
641 echo ${array[$code]}
642
643 ## STDOUT:
644 three
645 three
646 ## END
647
648 # it still dynamically parses
649
650 ## OK zsh STDOUT:
651 two
652 two
653 ## END
654
655
656 #### Is element set? test -v a[i]
657
658 # note: modern versions of zsh implement this
659
660 array=(1 2 3 '')
661
662 test -v 'array[1]'
663 echo set=$?
664
665 test -v 'array[3]'
666 echo empty=$?
667
668 test -v 'array[4]'
669 echo unset=$?
670
671 ## STDOUT:
672 set=0
673 empty=0
674 unset=1
675 ## END
676
677 ## N-I mksh STDOUT:
678 set=2
679 empty=2
680 unset=2
681 ## END
682
683
684 #### [[ -v a[i] ]]
685
686 # note: modern versions of zsh implement this
687
688 array=(1 2 3)
689 [[ -v array[1] ]]
690 echo status=$?
691
692 [[ -v array[4] ]]
693 echo status=$?
694
695 ## STDOUT:
696 status=0
697 status=1
698 ## END
699
700 ## N-I mksh status: 1
701 ## N-I mksh STDOUT:
702 ## END
703
704
705 #### test -v a[i] with arith expressions
706
707 array=(1 2 3 '')
708
709 test -v 'array[1+1]'
710 echo status=$?
711
712 test -v 'array[4+1]'
713 echo status=$?
714
715 echo
716 echo dbracket
717
718 [[ -v array[1+1] ]]
719 echo status=$?
720
721 [[ -v array[4+1] ]]
722 echo status=$?
723
724 ## STDOUT:
725 status=0
726 status=1
727
728 dbracket
729 status=0
730 status=1
731 ## END
732
733 ## N-I mksh status: 1
734 ## N-I mksh STDOUT:
735 status=2
736 status=2
737
738 dbracket
739 ## END
740
741
742 #### More arith expressions in [[ -v array[expr]] ]]
743
744 typeset -a array
745 array=('' nonempty)
746
747 # This feels inconsistent with the rest of bash?
748 zero=0
749
750 [[ -v array[zero+0] ]]
751 echo zero=$?
752
753 [[ -v array[zero+1] ]]
754 echo one=$?
755
756 [[ -v array[zero+2] ]]
757 echo two=$?
758
759 echo ---
760
761 i='0+0'
762 [[ -v array[i] ]]
763 echo zero=$?
764
765 i='0+1'
766 [[ -v array[i] ]]
767 echo one=$?
768
769 i='0+2'
770 [[ -v array[i] ]]
771 echo two=$?
772
773 echo ---
774
775 i='0+0'
776 [[ -v array[$i] ]]
777 echo zero=$?
778
779 i='0+1'
780 [[ -v array[$i] ]]
781 echo one=$?
782
783 i='0+2'
784 [[ -v array[$i] ]]
785 echo two=$?
786
787
788 ## STDOUT:
789 zero=0
790 one=0
791 two=1
792 ---
793 zero=0
794 one=0
795 two=1
796 ---
797 zero=0
798 one=0
799 two=1
800 ## END
801
802 ## N-I mksh status: 1
803 ## N-I mksh STDOUT:
804 ## END
805
806
807 #### Regression: Assigning with out-of-range negative index
808 a=()
809 a[-1]=1
810
811 ## status: 1
812 ## STDOUT:
813 ## END
814 ## STDERR:
815 a[-1]=1
816 ^~
817 [ stdin ]:2: fatal: Index -1 is out of bounds for array of length 0
818 ## END
819
820 ## OK bash STDERR:
821 bash: line 2: a[-1]: bad array subscript
822 ## END
823
824 # Note: mksh interprets -1 as 0xFFFFFFFF
825 ## N-I mksh status: 0
826 ## N-I mksh STDERR:
827 ## END
828
829
830 #### Regression: Negative index in [[ -v a[index] ]]
831 a[0]=x
832 a[5]=y
833 a[10]=z
834 [[ -v a[-1] ]] && echo 'a has -1'
835 [[ -v a[-2] ]] && echo 'a has -2'
836 [[ -v a[-5] ]] && echo 'a has -5'
837 [[ -v a[-6] ]] && echo 'a has -6'
838 [[ -v a[-10] ]] && echo 'a has -10'
839 [[ -v a[-11] ]] && echo 'a has -11'
840
841 ## STDOUT:
842 a has -1
843 a has -6
844 a has -11
845 ## END
846
847 ## N-I mksh status: 1
848 ## N-I mksh STDOUT:
849 ## END
850
851
852 #### Regression: Negative out-of-range index in [[ -v a[index] ]]
853 e=()
854 [[ -v e[-1] ]] && echo 'e has -1'
855
856 ## status: 1
857 ## STDERR:
858 [[ -v e[-1] ]] && echo 'e has -1'
859 ^
860 [ stdin ]:2: fatal: -v got index -1, which is out of bounds for array of length 0
861 ## END
862
863 ## OK bash STDERR:
864 bash: line 2: e: bad array subscript
865 ## END
866
867 ## N-I mksh STDERR:
868 mksh: <stdin>[2]: syntax error: 'e[-1]' unexpected operator/operand
869 ## END
870
871
872 #### a+=() modifies existing instance of BashArray
873 case $SH in mksh|bash) exit ;; esac
874
875 a=(1 2 3)
876 var b = a
877 a+=(4 5)
878 echo "a=(${a[*]})"
879 echo "b=(${b[*]})"
880
881 ## STDOUT:
882 a=(1 2 3 4 5)
883 b=(1 2 3 4 5)
884 ## END
885
886 ## N-I mksh/bash STDOUT:
887 ## END
888
889
890 #### Regression: unset a[-2]: out-of-bound negative index should cause error
891 case $SH in mksh) exit ;; esac
892
893 a=(1)
894 unset -v 'a[-2]'
895
896 ## status: 1
897 ## STDOUT:
898 ## END
899 ## STDERR:
900 unset -v 'a[-2]'
901 ^
902 [ stdin ]:4: a[-2]: Index is out of bounds for array of length 1
903 ## END
904
905 ## OK bash STDERR:
906 bash: line 4: unset: [-2]: bad array subscript
907 ## END
908
909 ## N-I mksh status: 0
910 ## N-I mksh STDERR:
911 ## END
912
913
914 #### Regression: Out-of-bound negative offset for ${a[@]:offset}
915 case $SH in mksh) exit ;; esac
916
917 a=(1 2 3 4)
918 echo "a=(${a[*]})"
919 echo "begin=-1 -> (${a[*]: -1})"
920 echo "begin=-2 -> (${a[*]: -2})"
921 echo "begin=-3 -> (${a[*]: -3})"
922 echo "begin=-4 -> (${a[*]: -4})"
923 echo "begin=-5 -> (${a[*]: -5})"
924
925 ## STDOUT:
926 a=(1 2 3 4)
927 begin=-1 -> (4)
928 begin=-2 -> (3 4)
929 begin=-3 -> (2 3 4)
930 begin=-4 -> (1 2 3 4)
931 begin=-5 -> ()
932 ## END
933
934 ## N-I mksh STDOUT:
935 ## END
936
937
938 #### Regression: Array length after unset
939 case $SH in mksh) exit ;; esac
940
941 a=(x)
942 a[9]=y
943 echo "len ${#a[@]};"
944
945 unset -v 'a[-1]'
946 echo "len ${#a[@]};"
947 echo "last ${a[@]: -1};"
948
949 ## STDOUT:
950 len 2;
951 len 1;
952 last x;
953 ## END
954
955 ## N-I mksh STDOUT:
956 ## END
957
958
959 #### Regression: ${a[@]@Q} crash with `a[0]=x a[2]=y`
960 case $SH in mksh) exit ;; esac
961
962 a[0]=x
963 a[2]=y
964 echo "quoted = (${a[@]@Q})"
965
966 ## STDOUT:
967 quoted = (x y)
968 ## END
969
970 ## OK bash STDOUT:
971 quoted = ('x' 'y')
972 ## END
973
974 ## N-I mksh STDOUT:
975 ## END
976
977
978 #### Regression: silent out-of-bound negative index in ${a[-2]} and $((a[-2]))
979 case $SH in mksh) exit ;; esac
980
981 a=(x)
982 echo "[${a[-2]}]"
983 echo $?
984 echo "[$((a[-2]))]"
985 echo $?
986
987 ## STDOUT:
988 []
989 0
990 [0]
991 0
992 ## END
993 ## STDERR:
994 echo "[${a[-2]}]"
995 ^
996 [ stdin ]:4: Index -2 out of bounds for array of length 1
997 echo "[$((a[-2]))]"
998 ^
999 [ stdin ]:6: Index -2 out of bounds for array of length 1
1000 ## END
1001
1002 ## OK bash STDERR:
1003 bash: line 4: a: bad array subscript
1004 bash: line 6: a: bad array subscript
1005 ## END
1006
1007 ## N-I mksh status: 0
1008 ## N-I mksh STDOUT:
1009 ## END
1010 ## N-I mksh STDERR:
1011 ## END