1 #!/bin/bash
2 #
3 # Test matching with case
4 #
5 # Usage:
6 # ./extglob-match.test.sh <function name>
7
8 #### @ matches exactly one
9 [[ --verbose == --@(help|verbose) ]] && echo TRUE
10 [[ --oops == --@(help|verbose) ]] || echo FALSE
11 ## STDOUT:
12 TRUE
13 FALSE
14 ## END
15
16 #### @() with variable arms
17 choice1='help'
18 choice2='verbose'
19 [[ --verbose == --@($choice1|$choice2) ]] && echo TRUE
20 [[ --oops == --@($choice1|$choice2) ]] || echo FALSE
21 ## STDOUT:
22 TRUE
23 FALSE
24 ## END
25
26 #### extglob in variable
27 shopt -s extglob
28 g=--@(help|verbose)
29 quoted='--@(help|verbose)'
30 [[ --help == $g ]] && echo TRUE
31 [[ --verbose == $g ]] && echo TRUE
32 [[ -- == $g ]] || echo FALSE
33 [[ --help == $q ]] || echo FALSE
34 [[ -- == $q ]] || echo FALSE
35 ## STDOUT:
36 TRUE
37 TRUE
38 FALSE
39 FALSE
40 FALSE
41 ## END
42 ## N-I mksh STDOUT:
43 FALSE
44 FALSE
45 FALSE
46 ## END
47
48 #### nested @()
49 shopt -s extglob
50 pat='--@(help|verbose|no-@(long|short)-option)'
51 [[ --no-long-option == $pat ]] && echo TRUE
52 [[ --no-short-option == $pat ]] && echo TRUE
53 [[ --help == $pat ]] && echo TRUE
54 [[ --oops == $pat ]] || echo FALSE
55 ## STDOUT:
56 TRUE
57 TRUE
58 TRUE
59 FALSE
60 ## END
61 ## BUG mksh STDOUT:
62 FALSE
63 ## END
64
65 #### nested @() with quotes and vars
66 shopt -s extglob
67 prefix=no
68 [[ --no-long-option == --@(help|verbose|$prefix-@(long|short)-'option') ]] &&
69 echo TRUE
70 ## STDOUT:
71 TRUE
72 ## END
73
74 #### ? matches 0 or 1
75 [[ -- == --?(help|verbose) ]] && echo TRUE
76 [[ --oops == --?(help|verbose) ]] || echo FALSE
77 ## STDOUT:
78 TRUE
79 FALSE
80 ## END
81
82 #### + matches 1 or more
83 [[ --helphelp == --+(help|verbose) ]] && echo TRUE
84 [[ -- == --+(help|verbose) ]] || echo FALSE
85 ## STDOUT:
86 TRUE
87 FALSE
88 ## END
89
90 #### * matches 0 or more
91 [[ -- == --*(help|verbose) ]] && echo TRUE
92 [[ --oops == --*(help|verbose) ]] || echo FALSE
93 ## STDOUT:
94 TRUE
95 FALSE
96 ## END
97
98 #### simple repetition with *(foo) and +(Foo)
99 [[ foofoo == *(foo) ]] && echo TRUE
100 [[ foofoo == +(foo) ]] && echo TRUE
101 ## STDOUT:
102 TRUE
103 TRUE
104 ## END
105
106 #### ! matches none
107 [[ --oops == --!(help|verbose) ]] && echo TRUE
108 [[ --help == --!(help|verbose) ]] || echo FALSE
109 ## STDOUT:
110 TRUE
111 FALSE
112 ## END
113
114 #### match is anchored
115 [[ foo_ == @(foo) ]] || echo FALSE
116 [[ _foo == @(foo) ]] || echo FALSE
117 [[ foo == @(foo) ]] && echo TRUE
118 ## STDOUT:
119 FALSE
120 FALSE
121 TRUE
122 ## END
123
124 #### repeated match is anchored
125 [[ foofoo_ == +(foo) ]] || echo FALSE
126 [[ _foofoo == +(foo) ]] || echo FALSE
127 [[ foofoo == +(foo) ]] && echo TRUE
128 ## STDOUT:
129 FALSE
130 FALSE
131 TRUE
132 ## END
133
134 #### repetition with glob
135 # NOTE that * means two different things here
136 [[ foofoo_foo__foo___ == *(foo*) ]] && echo TRUE
137 [[ Xoofoo_foo__foo___ == *(foo*) ]] || echo FALSE
138 ## STDOUT:
139 TRUE
140 FALSE
141 ## END
142
143 #### No brace expansion in ==
144 [[ --X{a,b}X == --@(help|X{a,b}X) ]] && echo TRUE
145 [[ --oops == --@(help|X{a,b}X) ]] || echo FALSE
146 ## STDOUT:
147 TRUE
148 FALSE
149 ## END
150
151 #### adjacent extglob
152 [[ --help == @(--|++)@(help|verbose) ]] && echo TRUE
153 [[ ++verbose == @(--|++)@(help|verbose) ]] && echo TRUE
154 ## STDOUT:
155 TRUE
156 TRUE
157 ## END
158
159 #### nested extglob
160 [[ --help == --@(help|verbose=@(1|2)) ]] && echo TRUE
161 [[ --verbose=1 == --@(help|verbose=@(1|2)) ]] && echo TRUE
162 [[ --verbose=2 == --@(help|verbose=@(1|2)) ]] && echo TRUE
163 [[ --verbose == --@(help|verbose=@(1|2)) ]] || echo FALSE
164 ## STDOUT:
165 TRUE
166 TRUE
167 TRUE
168 FALSE
169 ## END
170
171 #### extglob empty string
172 shopt -s extglob
173 [[ '' == @(foo|bar) ]] || echo FALSE
174 [[ '' == @(foo||bar) ]] && echo TRUE
175 ## STDOUT:
176 FALSE
177 TRUE
178 ## END
179
180 #### extglob empty pattern
181 shopt -s extglob
182 [[ '' == @() ]] && echo TRUE
183 [[ '' == @(||) ]] && echo TRUE
184 [[ X == @() ]] || echo FALSE
185 [[ '|' == @(||) ]] || echo FALSE
186 ## STDOUT:
187 TRUE
188 TRUE
189 FALSE
190 FALSE
191 ## END
192
193 #### case with extglob
194 shopt -s extglob
195 for word in --help --verbose --unmatched -- -zxzx -; do
196 case $word in
197 --@(help|verbose) )
198 echo A
199 continue
200 ;;
201 ( --?(b|c) )
202 echo B
203 continue
204 ;;
205 ( -+(x|z) )
206 echo C
207 continue
208 ;;
209 ( -*(x|z) )
210 echo D
211 continue
212 ;;
213 *)
214 echo U
215 continue
216 ;;
217 esac
218 done
219 ## STDOUT:
220 A
221 A
222 U
223 B
224 C
225 D
226 ## END
227
228 #### Without shopt -s extglob
229 empty=''
230 str='x'
231 [[ $empty == !($str) ]] && echo TRUE # test glob match
232 [[ $str == !($str) ]] || echo FALSE
233 ## STDOUT:
234 TRUE
235 FALSE
236 ## END
237
238 #### Turning extglob on changes the meaning of [[ !(str) ]] in bash
239 empty=''
240 str='x'
241 [[ !($empty) ]] && echo TRUE # test if $empty is empty
242 [[ !($str) ]] || echo FALSE # test if $str is empty
243 shopt -s extglob # mksh doesn't have this
244 [[ !($empty) ]] && echo TRUE # negated glob
245 [[ !($str) ]] && echo TRUE # negated glob
246 ## STDOUT:
247 TRUE
248 FALSE
249 TRUE
250 TRUE
251 ## END
252 ## OK osh/mksh STDOUT:
253 TRUE
254 TRUE
255 TRUE
256 ## END
257
258 #### With extglob on, !($str) on the left or right of == has different meanings
259 shopt -s extglob
260 empty=''
261 str='x'
262 [[ 1 == !($str) ]] && echo TRUE # glob match
263 [[ !($str) == 1 ]] || echo FALSE # test if empty
264 # NOTE: There cannot be a space between ! and (?
265 ## STDOUT:
266 TRUE
267 FALSE
268 ## END
269
270 #### extglob inside arg word
271 shopt -s extglob
272 [[ foo == @(foo|bar) ]] && echo TRUE
273 [[ foo == ${unset:-@(foo|bar)} ]] && echo TRUE
274 [[ fo == ${unset:-@(foo|bar)} ]] || echo FALSE
275 ## STDOUT:
276 TRUE
277 TRUE
278 FALSE
279 ## END
280 ## BUG mksh STDOUT:
281 TRUE
282 FALSE
283 ## END
284
285 #### extglob is not detected in regex!
286 shopt -s extglob
287 [[ foo =~ ^@(foo|bar)$ ]] || echo FALSE
288 ## STDOUT:
289 FALSE
290 ## END
291 ## N-I mksh stdout-json: ""
292 ## N-I mksh status: 1