1 ## compare_shells: bash dash mksh zsh
2 ## oils_failures_allowed: 1
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
148
149 # This doesn't make a difference on my local machine?
150 # Is the underlying issue how libc fnmatch() respects Unicode?
151
152 #LC_ALL=C
153 #LC_ALL=C.UTF-8
154
155 c=$(printf \\377)
156
157 # OSH prints -1 here
158 #echo "${#c}"
159
160 case $c in
161 '') echo a ;;
162 "$c") echo b ;;
163 esac
164
165 case "$c" in
166 '') echo a ;;
167 "$c") echo b ;;
168 esac
169
170 ## STDOUT:
171 b
172 b
173 ## END
174
175 #### matching every byte against itself
176
177 # Why does OSH on the CI machine behave differently? Probably a libc bug fix
178 # I'd guess?
179
180 #LC_ALL=C
181 #LC_ALL=C.UTF-8
182
183 sum=0
184
185 for i in $(seq 256); do
186 hex=$(printf '%x' $i)
187 c=$(printf "\\x$hex")
188 #echo -n $c | od -A n -t x1
189
190 case $c in
191 # Newline matches empty string somehow. All shells agree. I guess
192 # fnmatch() ignores trailing newline?
193
194 #'') echo "[bug i=$i hex=$hex c=$c]" ;;
195 "$c") sum=$(( sum + 1 )) ;;
196 *) echo "[bug i=$i hex=$hex c=$c]" ;;
197 esac
198 done
199
200 echo sum=$sum
201
202 ## STDOUT:
203 sum=256
204 ## END
205
206 #### \(\) in pattern (regression)
207 s='foo()'
208
209 case $s in
210 *\(\)) echo 'match'
211 esac
212
213 case $SH in (dash) exit;; esac # not implemented
214
215 shopt -s extglob
216
217 case $s in
218 *(foo|bar)'()') echo 'extglob'
219 esac
220 ## STDOUT:
221 match
222 extglob
223 ## END
224 ## N-I dash STDOUT:
225 match
226 ## END
227
228
229 #### case \n bug regression
230
231 case
232 in esac
233
234 ## STDOUT:
235 ## END
236 ## status: 2
237 ## OK mksh status: 1
238 ## OK zsh status: 127
239