1 ## compare_shells: bash dash mksh zsh
2 ## oils_failures_allowed: 0
3
4 # Note: zsh passes most of these tests too
5
6 #### Case statement
7 case a in
8 a) echo A ;;
9 *) echo star ;;
10 esac
11
12 for x in a b; do
13 case $x in
14 # the pattern is DYNAMIC and evaluated on every iteration
15 $x) echo loop ;;
16 *) echo star ;;
17 esac
18 done
19 ## STDOUT:
20 A
21 loop
22 loop
23 ## END
24
25 #### Case statement with ;;&
26 # ;;& keeps testing conditions
27 # NOTE: ;& and ;;& are bash 4 only, not on Mac
28 case a in
29 a) echo A ;;&
30 *) echo star ;;&
31 *) echo star2 ;;
32 esac
33 ## status: 0
34 ## STDOUT:
35 A
36 star
37 star2
38 ## END
39 ## N-I dash stdout-json: ""
40 ## N-I dash status: 2
41 ## N-I zsh stdout-json: ""
42 ## N-I zsh status: 1
43
44 #### Case statement with ;&
45 # ;& ignores the next condition. Why would that be useful?
46
47 for x in aa bb cc dd zz; do
48 case $x in
49 aa) echo aa ;&
50 bb) echo bb ;&
51 cc) echo cc ;;
52 dd) echo dd ;;
53 esac
54 echo --
55 done
56
57 ## status: 0
58 ## STDOUT:
59 aa
60 bb
61 cc
62 --
63 bb
64 cc
65 --
66 cc
67 --
68 dd
69 --
70 --
71 ## END
72 ## N-I dash stdout-json: ""
73 ## N-I dash status: 2
74
75 #### Case with empty condition
76 case $empty in
77 ''|foo) echo match ;;
78 *) echo no ;;
79 esac
80 ## stdout: match
81
82 #### Match a literal with a glob character
83 x='*.py'
84 case "$x" in
85 '*.py') echo match ;;
86 esac
87 ## stdout: match
88
89 #### Match a literal with a glob character with a dynamic pattern
90 x='b.py'
91 pat='[ab].py'
92 case "$x" in
93 $pat) echo match ;;
94 esac
95 ## stdout: match
96 ## BUG zsh stdout-json: ""
97
98 #### Quoted literal in glob pattern
99 x='[ab].py'
100 pat='[ab].py'
101 case "$x" in
102 "$pat") echo match ;;
103 esac
104 ## stdout: match
105
106 #### Multiple Patterns Match
107 x=foo
108 result='-'
109 case "$x" in
110 f*|*o) result="$result X"
111 esac
112 echo $result
113 ## stdout: - X
114
115 #### Pattern ? matches 1 code point (many bytes), but not multiple code points
116
117 # These two code points form a single character.
118 two_code_points="__$(echo $'\u0061\u0300')__"
119
120 # U+0061 is A, and U+0300 is an accent.
121 #
122 # (Example taken from # https://blog.golang.org/strings)
123 #
124 # However ? in bash/zsh only counts CODE POINTS. They do NOT take into account
125 # this case.
126
127 for s in '__a__' '__μ__' "$two_code_points"; do
128 case $s in
129 __?__)
130 echo yes
131 ;;
132 *)
133 echo no
134 esac
135 done
136 ## STDOUT:
137 yes
138 yes
139 no
140 ## END
141 ## BUG dash/mksh STDOUT:
142 yes
143 no
144 no
145 ## END
146
147 #### matching the byte 0xff against empty string - DISABLED - CI only bug?
148
149 case $SH in *osh) echo soil-ci-buster-slim-bug; exit ;; esac
150
151 # This doesn't make a difference on my local machine?
152 # Is the underlying issue how libc fnmatch() respects Unicode?
153
154 #LC_ALL=C
155 #LC_ALL=C.UTF-8
156
157 c=$(printf \\377)
158
159 # OSH prints -1 here
160 #echo "${#c}"
161
162 case $c in
163 '') echo a ;;
164 "$c") echo b ;;
165 esac
166
167 case "$c" in
168 '') echo a ;;
169 "$c") echo b ;;
170 esac
171
172 ## STDOUT:
173 b
174 b
175 ## END
176
177 ## OK osh STDOUT:
178 soil-ci-buster-slim-bug
179 ## END
180
181 #### matching every byte against itself
182
183 # Why does OSH on the CI machine behave differently? Probably a libc bug fix
184 # I'd guess?
185
186 sum=0
187
188 # note: NUL byte crashes OSH!
189 for i in $(seq 1 255); do
190 hex=$(printf '%x' "$i")
191 c="$(printf "\\x$hex")" # command sub quirk: \n or \x0a turns into empty string
192
193 #echo -n $c | od -A n -t x1
194 #echo ${#c}
195
196 case "$c" in
197 # Newline matches empty string somehow. All shells agree. I guess
198 # fnmatch() ignores trailing newline?
199 #'') echo "[empty i=$i hex=$hex c=$c]" ;;
200 "$c") sum=$(( sum + 1 )) ;;
201 *) echo "[bug i=$i hex=$hex c=$c]" ;;
202 esac
203 done
204
205 echo sum=$sum
206
207 ## STDOUT:
208 sum=255
209 ## END
210
211 #### \(\) in pattern (regression)
212 s='foo()'
213
214 case $s in
215 *\(\)) echo 'match'
216 esac
217
218 case $SH in (dash) exit;; esac # not implemented
219
220 shopt -s extglob
221
222 case $s in
223 *(foo|bar)'()') echo 'extglob'
224 esac
225 ## STDOUT:
226 match
227 extglob
228 ## END
229 ## N-I dash STDOUT:
230 match
231 ## END
232
233
234 #### case \n bug regression
235
236 case
237 in esac
238
239 ## STDOUT:
240 ## END
241 ## status: 2
242 ## OK mksh status: 1
243 ## OK zsh status: 127
244