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

402 lines, 235 significant
1## compare_shells: bash mksh
2
3# Test extended glob matching with [[, case, etc.
4
5#### @ matches exactly one
6shopt -s extglob # needed for Oil, not bash
7[[ --verbose == --@(help|verbose) ]] && echo TRUE
8[[ --oops == --@(help|verbose) ]] || echo FALSE
9## STDOUT:
10TRUE
11FALSE
12## END
13
14#### @() with variable arms
15shopt -s extglob # needed for Oil, not bash
16choice1='help'
17choice2='verbose'
18[[ --verbose == --@($choice1|$choice2) ]] && echo TRUE
19[[ --oops == --@($choice1|$choice2) ]] || echo FALSE
20## STDOUT:
21TRUE
22FALSE
23## END
24
25#### extglob in variable
26shopt -s extglob
27
28# this syntax requires extglob in bash!!
29# OSH never allows it
30g=--@(help|verbose)
31
32quoted='--@(help|verbose)'
33
34[[ --help == $g ]] && echo TRUE
35[[ --verbose == $g ]] && echo TRUE
36[[ -- == $g ]] || echo FALSE
37[[ --help == $q ]] || echo FALSE
38[[ -- == $q ]] || echo FALSE
39## STDOUT:
40TRUE
41TRUE
42FALSE
43FALSE
44FALSE
45## END
46## N-I mksh STDOUT:
47FALSE
48FALSE
49FALSE
50## END
51## OK osh status: 1
52## OK osh STDOUT:
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## OK mksh STDOUT:
298TRUE
299TRUE
300TRUE
301## END
302
303# osh fails with runtime error
304## OK osh status: 1
305## OK osh STDOUT:
306## END
307
308#### With extglob on, !($str) on the left or right of == has different meanings
309shopt -s extglob
310str='x'
311[[ 1 == !($str) ]] && echo TRUE # glob match
312
313## STDOUT:
314TRUE
315## END
316
317#### extglob inside arg word
318shopt -s extglob
319[[ foo == @(foo|bar) ]] && echo TRUE
320[[ foo == ${unset:-@(foo|bar)} ]] && echo TRUE
321[[ fo == ${unset:-@(foo|bar)} ]] || echo FALSE
322## STDOUT:
323TRUE
324TRUE
325FALSE
326## END
327## BUG mksh STDOUT:
328TRUE
329FALSE
330## END
331## OK osh status: 1
332## OK osh STDOUT:
333TRUE
334## END
335
336#### extglob is not detected in regex!
337shopt -s extglob
338[[ foo =~ ^@(foo|bar)$ ]] || echo FALSE
339## STDOUT:
340FALSE
341## END
342## N-I mksh stdout-json: ""
343## N-I mksh status: 1
344
345
346#### regular glob of single unicode char
347shopt -s extglob
348[[ __a__ == __?__ ]]
349echo $?
350[[ __μ__ == __?__ ]]
351echo $?
352## STDOUT:
3530
3540
355## END
356## BUG mksh STDOUT:
3570
3581
359## END
360
361#### extended glob of single unicode char
362shopt -s extglob
363[[ __a__ == @(__?__) ]]
364echo $?
365[[ __μ__ == @(__?__) ]]
366echo $?
367## STDOUT:
3680
3690
370## END
371## BUG mksh STDOUT:
3720
3731
374## END
375
376#### Extended glob in ${x//pat/replace}
377# not supported in OSH due to GlobToERE() strategy for positional info
378
379shopt -s extglob
380x=foo.py
381echo ${x//@(?.py)/Z}
382## STDOUT:
383foZ
384## END
385## N-I osh status: 1
386## N-I osh stdout-json: ""
387
388#### Extended glob in ${x%PATTERN}
389
390shopt -s extglob
391x=foo.py
392echo 'strip % ' ${x%.@(py|cc)}
393echo 'strip %%' ${x%%.@(py|cc)}
394echo 'strip # ' ${x#@(foo)}
395echo 'strip ##' ${x##@(foo)}
396
397## STDOUT:
398strip % foo
399strip %% foo
400strip # .py
401strip ## .py
402## END