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

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