OILS / spec / extglob-match.test.sh View on Github | oils.pub

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