1 |
# Test extended glob matching with [[, case, etc. |
2 |
|
3 |
#### @ matches exactly one |
4 |
shopt -s extglob # needed for Oil, not bash |
5 |
[[ --verbose == --@(help|verbose) ]] && echo TRUE |
6 |
[[ --oops == --@(help|verbose) ]] || echo FALSE |
7 |
## STDOUT: |
8 |
TRUE |
9 |
FALSE |
10 |
## END |
11 |
|
12 |
#### @() with variable arms |
13 |
shopt -s extglob # needed for Oil, not bash |
14 |
choice1='help' |
15 |
choice2='verbose' |
16 |
[[ --verbose == --@($choice1|$choice2) ]] && echo TRUE |
17 |
[[ --oops == --@($choice1|$choice2) ]] || echo FALSE |
18 |
## STDOUT: |
19 |
TRUE |
20 |
FALSE |
21 |
## END |
22 |
|
23 |
#### extglob in variable |
24 |
shopt -s extglob |
25 |
|
26 |
# this syntax requires extglob in bash!! |
27 |
# OSH never allows it |
28 |
g=--@(help|verbose) |
29 |
|
30 |
quoted='--@(help|verbose)' |
31 |
|
32 |
[[ --help == $g ]] && echo TRUE |
33 |
[[ --verbose == $g ]] && echo TRUE |
34 |
[[ -- == $g ]] || echo FALSE |
35 |
[[ --help == $q ]] || echo FALSE |
36 |
[[ -- == $q ]] || echo FALSE |
37 |
## STDOUT: |
38 |
TRUE |
39 |
TRUE |
40 |
FALSE |
41 |
FALSE |
42 |
FALSE |
43 |
## END |
44 |
## N-I mksh STDOUT: |
45 |
FALSE |
46 |
FALSE |
47 |
FALSE |
48 |
## END |
49 |
## OK osh status: 1 |
50 |
## OK osh STDOUT: |
51 |
## END |
52 |
|
53 |
#### Matching literal '@(cc)' |
54 |
|
55 |
# extglob is OFF. Doesn't affect bash or mksh! |
56 |
[[ cc == @(cc) ]] |
57 |
echo status=$? |
58 |
[[ cc == '@(cc)' ]] |
59 |
echo status=$? |
60 |
|
61 |
shopt -s extglob |
62 |
|
63 |
[[ cc == @(cc) ]] |
64 |
echo status=$? |
65 |
[[ cc == '@(cc)' ]] |
66 |
echo status=$? |
67 |
|
68 |
## STDOUT: |
69 |
status=0 |
70 |
status=1 |
71 |
status=0 |
72 |
status=1 |
73 |
## END |
74 |
|
75 |
#### nested @() |
76 |
shopt -s extglob |
77 |
pat='--@(help|verbose|no-@(long|short)-option)' |
78 |
[[ --no-long-option == $pat ]] && echo TRUE |
79 |
[[ --no-short-option == $pat ]] && echo TRUE |
80 |
[[ --help == $pat ]] && echo TRUE |
81 |
[[ --oops == $pat ]] || echo FALSE |
82 |
## STDOUT: |
83 |
TRUE |
84 |
TRUE |
85 |
TRUE |
86 |
FALSE |
87 |
## END |
88 |
## BUG mksh STDOUT: |
89 |
FALSE |
90 |
## END |
91 |
|
92 |
#### nested @() with quotes and vars |
93 |
shopt -s extglob |
94 |
prefix=no |
95 |
[[ --no-long-option == --@(help|verbose|$prefix-@(long|short)-'option') ]] && |
96 |
echo TRUE |
97 |
## STDOUT: |
98 |
TRUE |
99 |
## END |
100 |
|
101 |
#### ? matches 0 or 1 |
102 |
shopt -s extglob # needed for Oil, not bash |
103 |
[[ -- == --?(help|verbose) ]] && echo TRUE |
104 |
[[ --oops == --?(help|verbose) ]] || echo FALSE |
105 |
## STDOUT: |
106 |
TRUE |
107 |
FALSE |
108 |
## END |
109 |
|
110 |
#### + matches 1 or more |
111 |
shopt -s extglob # needed for Oil, not bash |
112 |
[[ --helphelp == --+(help|verbose) ]] && echo TRUE |
113 |
[[ -- == --+(help|verbose) ]] || echo FALSE |
114 |
## STDOUT: |
115 |
TRUE |
116 |
FALSE |
117 |
## END |
118 |
|
119 |
#### * matches 0 or more |
120 |
shopt -s extglob # needed for Oil, not bash |
121 |
[[ -- == --*(help|verbose) ]] && echo TRUE |
122 |
[[ --oops == --*(help|verbose) ]] || echo FALSE |
123 |
## STDOUT: |
124 |
TRUE |
125 |
FALSE |
126 |
## END |
127 |
|
128 |
#### simple repetition with *(foo) and +(Foo) |
129 |
shopt -s extglob # needed for Oil, not bash |
130 |
[[ foofoo == *(foo) ]] && echo TRUE |
131 |
[[ foofoo == +(foo) ]] && echo TRUE |
132 |
## STDOUT: |
133 |
TRUE |
134 |
TRUE |
135 |
## END |
136 |
|
137 |
#### ! matches none |
138 |
shopt -s extglob # needed for Oil, not bash |
139 |
[[ --oops == --!(help|verbose) ]] && echo TRUE |
140 |
[[ --help == --!(help|verbose) ]] || echo FALSE |
141 |
## STDOUT: |
142 |
TRUE |
143 |
FALSE |
144 |
## END |
145 |
|
146 |
#### match is anchored |
147 |
shopt -s extglob # needed for Oil, not bash |
148 |
[[ foo_ == @(foo) ]] || echo FALSE |
149 |
[[ _foo == @(foo) ]] || echo FALSE |
150 |
[[ foo == @(foo) ]] && echo TRUE |
151 |
## STDOUT: |
152 |
FALSE |
153 |
FALSE |
154 |
TRUE |
155 |
## END |
156 |
|
157 |
#### repeated match is anchored |
158 |
shopt -s extglob # needed for Oil, not bash |
159 |
[[ foofoo_ == +(foo) ]] || echo FALSE |
160 |
[[ _foofoo == +(foo) ]] || echo FALSE |
161 |
[[ foofoo == +(foo) ]] && echo TRUE |
162 |
## STDOUT: |
163 |
FALSE |
164 |
FALSE |
165 |
TRUE |
166 |
## END |
167 |
|
168 |
#### repetition with glob |
169 |
shopt -s extglob # needed for Oil, not bash |
170 |
|
171 |
# NOTE that * means two different things here |
172 |
[[ foofoo_foo__foo___ == *(foo*) ]] && echo TRUE |
173 |
[[ Xoofoo_foo__foo___ == *(foo*) ]] || echo FALSE |
174 |
## STDOUT: |
175 |
TRUE |
176 |
FALSE |
177 |
## END |
178 |
|
179 |
#### No brace expansion in == |
180 |
shopt -s extglob # needed for Oil, not bash |
181 |
|
182 |
[[ --X{a,b}X == --@(help|X{a,b}X) ]] && echo TRUE |
183 |
[[ --oops == --@(help|X{a,b}X) ]] || echo FALSE |
184 |
## STDOUT: |
185 |
TRUE |
186 |
FALSE |
187 |
## END |
188 |
|
189 |
#### adjacent extglob |
190 |
shopt -s extglob # needed for Oil, not bash |
191 |
|
192 |
[[ --help == @(--|++)@(help|verbose) ]] && echo TRUE |
193 |
[[ ++verbose == @(--|++)@(help|verbose) ]] && echo TRUE |
194 |
## STDOUT: |
195 |
TRUE |
196 |
TRUE |
197 |
## END |
198 |
|
199 |
#### nested extglob |
200 |
shopt -s extglob # needed for Oil, not bash |
201 |
|
202 |
[[ --help == --@(help|verbose=@(1|2)) ]] && echo TRUE |
203 |
[[ --verbose=1 == --@(help|verbose=@(1|2)) ]] && echo TRUE |
204 |
[[ --verbose=2 == --@(help|verbose=@(1|2)) ]] && echo TRUE |
205 |
[[ --verbose == --@(help|verbose=@(1|2)) ]] || echo FALSE |
206 |
## STDOUT: |
207 |
TRUE |
208 |
TRUE |
209 |
TRUE |
210 |
FALSE |
211 |
## END |
212 |
|
213 |
#### extglob empty string |
214 |
shopt -s extglob |
215 |
[[ '' == @(foo|bar) ]] || echo FALSE |
216 |
[[ '' == @(foo||bar) ]] && echo TRUE |
217 |
## STDOUT: |
218 |
FALSE |
219 |
TRUE |
220 |
## END |
221 |
|
222 |
#### extglob empty pattern |
223 |
shopt -s extglob |
224 |
[[ '' == @() ]] && echo TRUE |
225 |
[[ '' == @(||) ]] && echo TRUE |
226 |
[[ X == @() ]] || echo FALSE |
227 |
[[ '|' == @(||) ]] || echo FALSE |
228 |
## STDOUT: |
229 |
TRUE |
230 |
TRUE |
231 |
FALSE |
232 |
FALSE |
233 |
## END |
234 |
|
235 |
#### case with extglob |
236 |
shopt -s extglob |
237 |
for word in --help --verbose --unmatched -- -zxzx -; do |
238 |
case $word in |
239 |
--@(help|verbose) ) |
240 |
echo A |
241 |
continue |
242 |
;; |
243 |
( --?(b|c) ) |
244 |
echo B |
245 |
continue |
246 |
;; |
247 |
( -+(x|z) ) |
248 |
echo C |
249 |
continue |
250 |
;; |
251 |
( -*(x|z) ) |
252 |
echo D |
253 |
continue |
254 |
;; |
255 |
*) |
256 |
echo U |
257 |
continue |
258 |
;; |
259 |
esac |
260 |
done |
261 |
## STDOUT: |
262 |
A |
263 |
A |
264 |
U |
265 |
B |
266 |
C |
267 |
D |
268 |
## END |
269 |
|
270 |
#### [[ $x == !($str) ]] |
271 |
shopt -s extglob |
272 |
empty='' |
273 |
str='x' |
274 |
[[ $empty == !($str) ]] && echo TRUE # test glob match |
275 |
[[ $str == !($str) ]] || echo FALSE |
276 |
## STDOUT: |
277 |
TRUE |
278 |
FALSE |
279 |
## END |
280 |
|
281 |
#### Turning extglob on changes the meaning of [[ !(str) ]] in bash |
282 |
empty='' |
283 |
str='x' |
284 |
[[ !($empty) ]] && echo TRUE # test if $empty is empty |
285 |
[[ !($str) ]] || echo FALSE # test if $str is empty |
286 |
shopt -s extglob # mksh doesn't have this |
287 |
[[ !($empty) ]] && echo TRUE # negated glob |
288 |
[[ !($str) ]] && echo TRUE # negated glob |
289 |
## STDOUT: |
290 |
TRUE |
291 |
FALSE |
292 |
TRUE |
293 |
TRUE |
294 |
## END |
295 |
## OK mksh STDOUT: |
296 |
TRUE |
297 |
TRUE |
298 |
TRUE |
299 |
## END |
300 |
|
301 |
# osh fails wth runtime error |
302 |
## OK osh status: 1 |
303 |
## OK osh STDOUT: |
304 |
## END |
305 |
|
306 |
#### With extglob on, !($str) on the left or right of == has different meanings |
307 |
shopt -s extglob |
308 |
str='x' |
309 |
[[ 1 == !($str) ]] && echo TRUE # glob match |
310 |
|
311 |
## STDOUT: |
312 |
TRUE |
313 |
## END |
314 |
|
315 |
#### extglob inside arg word |
316 |
shopt -s extglob |
317 |
[[ foo == @(foo|bar) ]] && echo TRUE |
318 |
[[ foo == ${unset:-@(foo|bar)} ]] && echo TRUE |
319 |
[[ fo == ${unset:-@(foo|bar)} ]] || echo FALSE |
320 |
## STDOUT: |
321 |
TRUE |
322 |
TRUE |
323 |
FALSE |
324 |
## END |
325 |
## BUG mksh STDOUT: |
326 |
TRUE |
327 |
FALSE |
328 |
## END |
329 |
## OK osh status: 1 |
330 |
## OK osh STDOUT: |
331 |
TRUE |
332 |
## END |
333 |
|
334 |
#### extglob is not detected in regex! |
335 |
shopt -s extglob |
336 |
[[ foo =~ ^@(foo|bar)$ ]] || echo FALSE |
337 |
## STDOUT: |
338 |
FALSE |
339 |
## END |
340 |
## N-I mksh stdout-json: "" |
341 |
## N-I mksh status: 1 |
342 |
|
343 |
|
344 |
#### regular glob of single unicode char |
345 |
shopt -s extglob |
346 |
[[ __a__ == __?__ ]] |
347 |
echo $? |
348 |
[[ __μ__ == __?__ ]] |
349 |
echo $? |
350 |
## STDOUT: |
351 |
0 |
352 |
0 |
353 |
## END |
354 |
## BUG mksh STDOUT: |
355 |
0 |
356 |
1 |
357 |
## END |
358 |
|
359 |
#### extended glob of single unicode char |
360 |
shopt -s extglob |
361 |
[[ __a__ == @(__?__) ]] |
362 |
echo $? |
363 |
[[ __μ__ == @(__?__) ]] |
364 |
echo $? |
365 |
## STDOUT: |
366 |
0 |
367 |
0 |
368 |
## END |
369 |
## BUG mksh STDOUT: |
370 |
0 |
371 |
1 |
372 |
## END |
373 |
|
374 |
#### Extended glob in ${x//pat/replace} |
375 |
# not supported in OSH due to GlobToERE() strategy for positional info |
376 |
|
377 |
shopt -s extglob |
378 |
x=foo.py |
379 |
echo ${x//@(?.py)/Z} |
380 |
## STDOUT: |
381 |
foZ |
382 |
## END |
383 |
## N-I osh status: 1 |
384 |
## N-I osh stdout-json: "" |
385 |
|
386 |
#### Extended glob in ${x%PATTERN} |
387 |
|
388 |
shopt -s extglob |
389 |
x=foo.py |
390 |
echo 'strip % ' ${x%.@(py|cc)} |
391 |
echo 'strip %%' ${x%%.@(py|cc)} |
392 |
echo 'strip # ' ${x#@(foo)} |
393 |
echo 'strip ##' ${x##@(foo)} |
394 |
|
395 |
## STDOUT: |
396 |
strip % foo |
397 |
strip %% foo |
398 |
strip # .py |
399 |
strip ## .py |
400 |
## END |