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:
281 a
282 (b b)
283 ## END
284 ## OK bash status: 0
285 ## OK mksh status: 1
286
287 #### Associative arrays can't be used as env bindings either
288 A=a B=([k]=v) printenv.py A B
289 ## status: 2
290 ## stdout-json: ""
291 ## OK bash STDOUT:
292 a
293 ([k]=v)
294 ## OK bash status: 0
295 ## OK mksh status: 1
296
297 #### Set element
298 a=(1 '2 3')
299 a[0]=9
300 argv.py "${a[@]}"
301 ## stdout: ['9', '2 3']
302
303 #### Set element with var ref
304 a=(1 '2 3')
305 i=0
306 a[$i]=9
307 argv.py "${a[@]}"
308 ## stdout: ['9', '2 3']
309
310 #### Set element with array ref
311 # This makes parsing a little more complex. Anything can be inside [],
312 # including other [].
313 a=(1 '2 3')
314 i=(0 1)
315 a[${i[1]}]=9
316 argv.py "${a[@]}"
317 ## stdout: ['1', '9']
318
319 #### Set array item to array
320 a=(1 2)
321 a[0]=(3 4)
322 echo "status=$?"
323 ## stdout-json: ""
324 ## status: 2
325 ## N-I mksh status: 1
326 ## BUG bash stdout: status=1
327 ## BUG bash status: 0
328
329 #### Slice of array with [@]
330 # mksh doesn't support this syntax! It's a bash extension.
331 a=(1 2 3)
332 argv.py "${a[@]:1:2}"
333 ## stdout: ['2', '3']
334 ## N-I mksh status: 1
335 ## N-I mksh stdout-json: ""
336
337 #### Negative slice begin
338 # mksh doesn't support this syntax! It's a bash extension.
339 # NOTE: for some reason -2) has to be in parens? Ah that's because it
340 # conflicts with :-! That's silly. You can also add a space.
341 a=(1 2 3 4 5)
342 argv.py "${a[@]:(-4)}"
343 ## stdout: ['2', '3', '4', '5']
344 ## N-I mksh status: 1
345 ## N-I mksh stdout-json: ""
346
347 #### Negative slice length
348 a=(1 2 3 4 5)
349 argv.py "${a[@]: 1: -3}"
350 ## status: 1
351 ## stdout-json: ""
352
353 #### Slice with arithmetic
354 a=(1 2 3)
355 i=5
356 argv.py "${a[@]:i-4:2}"
357 ## stdout: ['2', '3']
358 ## N-I mksh status: 1
359 ## N-I mksh stdout-json: ""
360
361 #### Number of elements
362 a=(1 '2 3')
363 echo "${#a[@]}" ${#a[@]} # bug fix: also test without quotes
364 ## stdout: 2 2
365
366 #### Length of an element
367 a=(1 '2 3')
368 echo "${#a[1]}"
369 ## stdout: 3
370
371 #### Iteration
372 a=(1 '2 3')
373 for v in "${a[@]}"; do
374 echo $v
375 done
376 ## STDOUT:
377 1
378 2 3
379 ## END
380
381 #### glob within array yields separate elements
382 touch _tmp/y.Y _tmp/yy.Y
383 a=(_tmp/*.Y)
384 argv.py "${a[@]}"
385 ## stdout: ['_tmp/y.Y', '_tmp/yy.Y']
386
387 #### declare array and then append
388 declare -a array
389 array+=(a)
390 array+=(b c)
391 argv.py "${array[@]}"
392 ## stdout: ['a', 'b', 'c']
393
394 #### Array syntax in wrong place
395 ls foo=(1 2)
396 ## status: 1
397 ## OK bash status: 2
398
399 #### Single array with :-
400
401 # 2024-06 - bash 5.2 and mksh now match, bash 4.4 differed.
402 # Could change OSH
403 # zsh agrees with OSH, but it fails most test cases
404 # 2025-01 We changed OSH.
405
406 single=('')
407 argv.py ${single[@]:-none} x "${single[@]:-none}"
408 ## stdout: ['none', 'x', 'none']
409
410 #### Stripping a whole array unquoted
411 # Problem: it joins it first.
412 files=('foo.c' 'sp ace.h' 'bar.c')
413 argv.py ${files[@]%.c}
414 ## status: 0
415 ## stdout: ['foo', 'sp', 'ace.h', 'bar']
416 ## N-I mksh status: 1
417 ## N-I mksh stdout-json: ""
418
419 #### Stripping a whole array quoted
420 files=('foo.c' 'sp ace.h' 'bar.c')
421 argv.py "${files[@]%.c}"
422 ## status: 0
423 ## stdout: ['foo', 'sp ace.h', 'bar']
424 ## N-I mksh status: 1
425 ## N-I mksh stdout-json: ""
426
427 #### Multiple subscripts not allowed
428 # NOTE: bash 4.3 had a bug where it ignored the bad subscript, but now it is
429 # fixed.
430 a=('123' '456')
431 argv.py "${a[0]}" "${a[0][0]}"
432 ## stdout-json: ""
433 ## status: 2
434 ## OK bash/mksh status: 1
435
436 #### Length op, index op, then transform op is not allowed
437 a=('123' '456')
438 echo "${#a[0]}" "${#a[0]/1/xxx}"
439 ## stdout-json: ""
440 ## status: 2
441 ## OK bash/mksh status: 1
442
443 #### ${mystr[@]} and ${mystr[*]} are no-ops
444 s='abc'
445 echo ${s[@]}
446 echo ${s[*]}
447 ## STDOUT:
448 abc
449 abc
450 ## END
451
452 #### ${mystr[@]} and ${mystr[*]} disallowed with strict_array
453
454 $SH -c 'shopt -s strict_array; s="abc"; echo ${s[@]}'
455 echo status=$?
456
457 $SH -c 'shopt -s strict_array; s="abc"; echo ${s[*]}'
458 echo status=$?
459
460 ## status: 0
461 ## STDOUT:
462 status=1
463 status=1
464 ## END
465 ## N-I bash/mksh STDOUT:
466 abc
467 status=0
468 abc
469 status=0
470 ## END
471
472 #### Create a "user" array out of the argv array
473 set -- 'a b' 'c'
474 array1=('x y' 'z')
475 array2=("$@")
476 argv.py "${array1[@]}" "${array2[@]}"
477 ## stdout: ['x y', 'z', 'a b', 'c']
478
479 #### Tilde expansion within array
480 HOME=/home/bob
481 a=(~/src ~/git)
482 echo "${a[@]}"
483 ## stdout: /home/bob/src /home/bob/git
484
485 #### Brace Expansion within Array
486 a=(-{a,b} {c,d}-)
487 echo "${a[@]}"
488 ## stdout: -a -b c- d-
489
490 #### array default
491 default=('1 2' '3')
492 argv.py "${undef[@]:-${default[@]}}"
493 ## stdout: ['1 2', '3']
494
495 #### Singleton Array Copy and Assign. OSH can't index strings with ints
496 a=( '12 3' )
497 b=( "${a[@]}" )
498 c="${a[@]}" # This decays it to a string
499 d=${a[*]} # This decays it to a string
500 echo ${#a[0]} ${#b[0]}
501 echo ${#a[@]} ${#b[@]}
502
503 # osh is intentionally stricter, and these fail.
504 echo ${#c[0]} ${#d[0]}
505 echo ${#c[@]} ${#d[@]}
506
507 ## status: 1
508 ## STDOUT:
509 4 4
510 1 1
511 ## END
512 ## OK bash/mksh status: 0
513 ## OK bash/mksh STDOUT:
514 4 4
515 1 1
516 4 4
517 1 1
518 ## END
519
520 #### declare -a / local -a is empty array
521 declare -a myarray
522 argv.py "${myarray[@]}"
523 myarray+=('x')
524 argv.py "${myarray[@]}"
525
526 f() {
527 local -a myarray
528 argv.py "${myarray[@]}"
529 myarray+=('x')
530 argv.py "${myarray[@]}"
531 }
532 f
533 ## STDOUT:
534 []
535 ['x']
536 []
537 ['x']
538 ## END
539
540 #### Create sparse array
541 a=()
542 (( a[99]=1 )) # osh doesn't parse index assignment outside arithmetic yet
543 echo len=${#a[@]}
544 argv.py "${a[@]}"
545 echo "unset=${a[33]}"
546 echo len-of-unset=${#a[33]}
547 ## STDOUT:
548 len=1
549 ['1']
550 unset=
551 len-of-unset=0
552 ## END
553
554 #### Create sparse array implicitly
555 (( a[99]=1 ))
556 echo len=${#a[@]}
557 argv.py "${a[@]}"
558 echo "unset=${a[33]}"
559 echo len-of-unset=${#a[33]}
560 ## STDOUT:
561 len=1
562 ['1']
563 unset=
564 len-of-unset=0
565 ## END
566
567 #### Append sparse arrays
568 a=()
569 (( a[99]=1 ))
570 b=()
571 (( b[33]=2 ))
572 (( b[66]=3 ))
573 a+=( "${b[@]}" )
574 argv.py "${a[@]}"
575 argv.py "${a[99]}" "${a[100]}" "${a[101]}"
576 ## STDOUT:
577 ['1', '2', '3']
578 ['1', '2', '3']
579 ## END
580
581 #### Slice of sparse array with [@]
582 # mksh doesn't support this syntax! It's a bash extension.
583 (( a[33]=1 ))
584 (( a[66]=2 ))
585 (( a[99]=2 ))
586 argv.py "${a[@]:15:2}"
587 ## stdout: ['1', '2']
588 ## N-I mksh status: 1
589 ## N-I mksh stdout-json: ""
590
591 #### Using an array itself as the index on LHS
592 shopt -u strict_arith
593 a[a]=42
594 a[a]=99
595 argv.py "${a[@]}" "${a[0]}" "${a[42]}" "${a[99]}"
596
597 ## status: 0
598 ## STDOUT:
599 ['42', '99', '42', '99', '']
600 ## END
601
602 #### Using an array itself as the index on RHS
603 shopt -u strict_arith
604 a=(1 2 3)
605 (( x = a[a] ))
606 echo $x
607 ## status: 0
608 ## STDOUT:
609 2
610 ## END
611
612 #### a[$x$y] on LHS and RHS
613 x=1
614 y=2
615 a[$x$y]=foo
616
617 # not allowed by OSH parsing
618 #echo ${a[$x$y]}
619
620 echo ${a[12]}
621 echo ${#a[@]}
622
623 ## STDOUT:
624 foo
625 1
626 ## END
627
628
629 #### Dynamic parsing of LHS a[$code]=value
630
631 declare -a array
632 array[x=1]='one'
633
634 code='y=2'
635 #code='1+2' # doesn't work either
636 array[$code]='two'
637
638 argv.py "${array[@]}"
639 echo x=$x
640 echo y=$y
641
642 ## STDOUT:
643 ['one', 'two']
644 x=1
645 y=2
646 ## END
647 ## N-I dash stdout-json: ""
648 ## N-I dash status: 2
649
650 #### Dynamic parsing of RHS ${a[$code]}
651 declare -a array
652 array=(zero one two three)
653
654 echo ${array[1+2]}
655
656 code='1+2'
657 echo ${array[$code]}
658
659 ## STDOUT:
660 three
661 three
662 ## END
663
664 # it still dynamically parses
665
666 ## OK zsh STDOUT:
667 two
668 two
669 ## END
670
671
672 #### Is element set? test -v a[i]
673
674 # note: modern versions of zsh implement this
675
676 array=(1 2 3 '')
677
678 test -v 'array[1]'
679 echo set=$?
680
681 test -v 'array[3]'
682 echo empty=$?
683
684 test -v 'array[4]'
685 echo unset=$?
686
687 ## STDOUT:
688 set=0
689 empty=0
690 unset=1
691 ## END
692
693 ## N-I mksh STDOUT:
694 set=2
695 empty=2
696 unset=2
697 ## END
698
699
700 #### [[ -v a[i] ]]
701
702 # note: modern versions of zsh implement this
703
704 array=(1 2 3)
705 [[ -v array[1] ]]
706 echo status=$?
707
708 [[ -v array[4] ]]
709 echo status=$?
710
711 ## STDOUT:
712 status=0
713 status=1
714 ## END
715
716 ## N-I mksh status: 1
717 ## N-I mksh STDOUT:
718 ## END
719
720
721 #### test -v a[i] with arith expressions
722
723 array=(1 2 3 '')
724
725 test -v 'array[1+1]'
726 echo status=$?
727
728 test -v 'array[4+1]'
729 echo status=$?
730
731 echo
732 echo dbracket
733
734 [[ -v array[1+1] ]]
735 echo status=$?
736
737 [[ -v array[4+1] ]]
738 echo status=$?
739
740 ## STDOUT:
741 status=0
742 status=1
743
744 dbracket
745 status=0
746 status=1
747 ## END
748
749 ## N-I mksh status: 1
750 ## N-I mksh STDOUT:
751 status=2
752 status=2
753
754 dbracket
755 ## END
756
757
758 #### More arith expressions in [[ -v array[expr]] ]]
759
760 typeset -a array
761 array=('' nonempty)
762
763 # This feels inconsistent with the rest of bash?
764 zero=0
765
766 [[ -v array[zero+0] ]]
767 echo zero=$?
768
769 [[ -v array[zero+1] ]]
770 echo one=$?
771
772 [[ -v array[zero+2] ]]
773 echo two=$?
774
775 echo ---
776
777 i='0+0'
778 [[ -v array[i] ]]
779 echo zero=$?
780
781 i='0+1'
782 [[ -v array[i] ]]
783 echo one=$?
784
785 i='0+2'
786 [[ -v array[i] ]]
787 echo two=$?
788
789 echo ---
790
791 i='0+0'
792 [[ -v array[$i] ]]
793 echo zero=$?
794
795 i='0+1'
796 [[ -v array[$i] ]]
797 echo one=$?
798
799 i='0+2'
800 [[ -v array[$i] ]]
801 echo two=$?
802
803
804 ## STDOUT:
805 zero=0
806 one=0
807 two=1
808 ---
809 zero=0
810 one=0
811 two=1
812 ---
813 zero=0
814 one=0
815 two=1
816 ## END
817
818 ## N-I mksh status: 1
819 ## N-I mksh STDOUT:
820 ## END
821
822
823 #### Regression: Assigning with out-of-range negative index
824 a=()
825 a[-1]=1
826
827 ## status: 1
828 ## STDOUT:
829 ## END
830 ## STDERR:
831 a[-1]=1
832 ^~
833 [ stdin ]:2: fatal: Index -1 is out of bounds for array of length 0
834 ## END
835
836 ## OK bash STDERR:
837 bash: line 2: a[-1]: bad array subscript
838 ## END
839
840 # Note: mksh interprets -1 as 0xFFFFFFFF
841 ## N-I mksh status: 0
842 ## N-I mksh STDERR:
843 ## END
844
845
846 #### Regression: Negative index in [[ -v a[index] ]]
847 a[0]=x
848 a[5]=y
849 a[10]=z
850 [[ -v a[-1] ]] && echo 'a has -1'
851 [[ -v a[-2] ]] && echo 'a has -2'
852 [[ -v a[-5] ]] && echo 'a has -5'
853 [[ -v a[-6] ]] && echo 'a has -6'
854 [[ -v a[-10] ]] && echo 'a has -10'
855 [[ -v a[-11] ]] && echo 'a has -11'
856
857 ## STDOUT:
858 a has -1
859 a has -6
860 a has -11
861 ## END
862
863 ## N-I mksh status: 1
864 ## N-I mksh STDOUT:
865 ## END
866
867
868 #### Regression: Negative out-of-range index in [[ -v a[index] ]]
869 e=()
870 [[ -v e[-1] ]] && echo 'e has -1'
871
872 ## status: 1
873 ## STDERR:
874 [[ -v e[-1] ]] && echo 'e has -1'
875 ^
876 [ stdin ]:2: fatal: -v got index -1, which is out of bounds for array of length 0
877 ## END
878
879 ## OK bash STDERR:
880 bash: line 2: e: bad array subscript
881 ## END
882
883 ## N-I mksh STDERR:
884 mksh: <stdin>[2]: syntax error: 'e[-1]' unexpected operator/operand
885 ## END
886
887
888 #### a+=() modifies existing instance of BashArray
889 case $SH in mksh|bash) exit ;; esac
890
891 a=(1 2 3)
892 var b = a
893 a+=(4 5)
894 echo "a=(${a[*]})"
895 echo "b=(${b[*]})"
896
897 ## STDOUT:
898 a=(1 2 3 4 5)
899 b=(1 2 3 4 5)
900 ## END
901
902 ## N-I mksh/bash STDOUT:
903 ## END
904
905
906 #### Regression: unset a[-2]: out-of-bound negative index should cause error
907 case $SH in mksh) exit ;; esac
908
909 a=(1)
910 unset -v 'a[-2]'
911
912 ## status: 1
913 ## STDOUT:
914 ## END
915 ## STDERR:
916 unset -v 'a[-2]'
917 ^
918 [ stdin ]:4: a[-2]: Index is out of bounds for array of length 1
919 ## END
920
921 ## OK bash STDERR:
922 bash: line 4: unset: [-2]: bad array subscript
923 ## END
924
925 ## N-I mksh status: 0
926 ## N-I mksh STDERR:
927 ## END
928
929
930 #### Regression: Out-of-bound negative offset for ${a[@]:offset}
931 case $SH in mksh) exit ;; esac
932
933 a=(1 2 3 4)
934 echo "a=(${a[*]})"
935 echo "begin=-1 -> (${a[*]: -1})"
936 echo "begin=-2 -> (${a[*]: -2})"
937 echo "begin=-3 -> (${a[*]: -3})"
938 echo "begin=-4 -> (${a[*]: -4})"
939 echo "begin=-5 -> (${a[*]: -5})"
940
941 ## STDOUT:
942 a=(1 2 3 4)
943 begin=-1 -> (4)
944 begin=-2 -> (3 4)
945 begin=-3 -> (2 3 4)
946 begin=-4 -> (1 2 3 4)
947 begin=-5 -> ()
948 ## END
949
950 ## N-I mksh STDOUT:
951 ## END
952
953
954 #### Regression: Array length after unset
955 case $SH in mksh) exit ;; esac
956
957 a=(x)
958 a[9]=y
959 echo "len ${#a[@]};"
960
961 unset -v 'a[-1]'
962 echo "len ${#a[@]};"
963 echo "last ${a[@]: -1};"
964
965 ## STDOUT:
966 len 2;
967 len 1;
968 last x;
969 ## END
970
971 ## N-I mksh STDOUT:
972 ## END
973
974
975 #### Regression: ${a[@]@Q} crash with `a[0]=x a[2]=y`
976 case $SH in mksh) exit ;; esac
977
978 a[0]=x
979 a[2]=y
980 echo "quoted = (${a[@]@Q})"
981
982 ## STDOUT:
983 quoted = (x y)
984 ## END
985
986 ## OK bash STDOUT:
987 quoted = ('x' 'y')
988 ## END
989
990 ## N-I mksh STDOUT:
991 ## END
992
993
994 #### Regression: silent out-of-bound negative index in ${a[-2]} and $((a[-2]))
995 case $SH in mksh) exit ;; esac
996
997 a=(x)
998 echo "[${a[-2]}]"
999 echo $?
1000 echo "[$((a[-2]))]"
1001 echo $?
1002
1003 ## STDOUT:
1004 []
1005 0
1006 [0]
1007 0
1008 ## END
1009 ## STDERR:
1010 echo "[${a[-2]}]"
1011 ^
1012 [ stdin ]:4: Index -2 out of bounds for array of length 1
1013 echo "[$((a[-2]))]"
1014 ^
1015 [ stdin ]:6: Index -2 out of bounds for array of length 1
1016 ## END
1017
1018 ## OK bash STDERR:
1019 bash: line 4: a: bad array subscript
1020 bash: line 6: a: bad array subscript
1021 ## END
1022
1023 ## N-I mksh status: 0
1024 ## N-I mksh STDOUT:
1025 ## END
1026 ## N-I mksh STDERR:
1027 ## END