#!/usr/bin/zsh -f setopt extendedglob badpattern unsetopt kshglob failed=0 while read res str pat; do [[ $res = '#' ]] && continue [[ $str = ${~pat} ]] ts=$? [[ $1 = -q ]] || print "$ts: [[ $str = $pat ]]" if [[ ( $ts -gt 0 && $res = t) || ($ts -eq 0 && $res = f) ]]; then print "Test failed: [[ $str = $pat ]]" (( failed++ )) fi done <<EOT # a few simple things certain nameless idiots have been known to mess up t foo~ foo~ t foo~ (foo~) t foo~ (foo~|) t foo.c *.c~boo* f foo.c *.c~boo*~foo* # closures t fofo (fo#)# t ffo (fo#)# t foooofo (fo#)# t foooofof (fo#)# t fooofoofofooo (fo#)# f foooofof (fo##)# f xfoooofof (fo#)# f foooofofx (fo#)# t ofxoofxo ((ofo#x)#o)# f ofooofoofofooo (fo#)# t foooxfooxfoxfooox (fo#x)# f foooxfooxofoxfooox (fo#x)# t foooxfooxfxfooox (fo#x)# t ofxoofxo ((ofo#x)#o)# t ofoooxoofxo ((ofo#x)#o)# t ofoooxoofxoofoooxoofxo ((ofo#x)#o)# t ofoooxoofxoofoooxoofxoo ((ofo#x)#o)# f ofoooxoofxoofoooxoofxofo ((ofo#x)#o)# t ofoooxoofxoofoooxoofxooofxofxo ((ofo#x)#o)# t aac ((a))#a(c) t ac ((a))#a(c) f c ((a))#a(c) t aaac ((a))#a(c) f baaac ((a))#a(c) t abcd ?(a|b)c#d t abcd (ab|ab#)c#d t acd (ab|ab#)c#d t abbcd (ab|ab#)c#d t effgz (bc##d|ef#g?|(h|)i(j|k)) t efgz (bc##d|ef#g?|(h|)i(j|k)) t egz (bc##d|ef#g?|(h|)i(j|k)) t egzefffgzbcdij (bc##d|ef#g?|(h|)i(j|k))# f egz (bc##d|ef##g?|(h|)i(j|k)) t ofoofo (ofo##)# t oxfoxoxfox (oxf(ox)##)# f oxfoxfox (oxf(ox)##)# t ofoofo (ofo##|f)# # The following is supposed to match only as fo+ofo+ofo t foofoofo (foo|f|fo)(f|ofo##)# t oofooofo (of|oofo##)# t fffooofoooooffoofffooofff (f#o#)# # If the following is really slow, that's a bug. f fffooofoooooffoofffooofffx (f#o#)# # The following tests backtracking in alternation matches t fofoofoofofoo (fo|foo)# # Exclusion: test both types t foo ((^x)) t foo ((^x)*) f foo ((^foo)) t foo ((^foo)*) t foobar ((^foo)) t foobar ((^foo)*) f foot z*~*x t zoot z*~*x f foox z*~*x f zoox z*~*x t moo.cow (*~*.*).(*~*.*) f mad.moo.cow (*~*.*).(*~*.*) t moo.cow (^*.*).(^*.*) f sane.moo.cow (^*.*).(^*.*) f mucca.pazza mu(^c#)?.pa(^z#)? f _foo~ _(|*[^~]) t fff ((^f)) t fff ((^f)#) t fff ((^f)##) t ooo ((^f)) t ooo ((^f)#) t ooo ((^f)##) t foo ((^f)) t foo ((^f)#) t foo ((^f)##) f f ((^f)) f f ((^f)#) f f ((^f)##) t foot (^z*|*x) f zoot (^z*|*x) t foox (^z*|*x) t zoox (^z*|*x) t foo (^foo)# f foob (^foo)b* t foobb (^foo)b* f foob (*~foo)b* t foobb (*~foo)b* f zsh ^z* t a%1X [[:alpha:][:punct:]]#[[:digit:]][^[:lower:]] f a%1 [[:alpha:][:punct:]]#[[:digit:]][^[:lower:]] t [: [[:]# t :] []:]# t :] [:]]# t [ [[] t ] []] t [] [^]]] # Case insensitive matching t fooxx (#i)FOOXX f fooxx (#l)FOOXX t FOOXX (#l)fooxx f fooxx (#i)FOO(#I)X(#i)X t fooXx (#i)FOO(#I)X(#i)X t fooxx ((#i)FOOX)x f fooxx ((#i)FOOX)X f BAR (bar|(#i)foo) t FOO (bar|(#i)foo) t Modules (#i)*m* t fooGRUD (#i)(bar|(#I)foo|(#i)rod)grud f FOOGRUD (#i)(bar|(#I)foo|(#i)rod)grud t readme (#i)readme~README|readme # the readme doesn't get excluded the second time... t readme (#i)readme~README|readme~README # Ranges with backtracking t 633 <1-1000>33 t 633 <-1000>33 t 633 <1->33 t 633 <->33 # An open top end of a range will match any integer, even # if not representable in the internal integer type. t 12345678901234567890123456789012345678901234567890123456789012345678901234567890foo <42->foo # Approximate matching t READ.ME (#ia1)readme f READ..ME (#ia1)readme t README (#ia1)readm t READM (#ia1)readme t README (#ia1)eadme t EADME (#ia1)readme t READEM (#ia1)readme f ADME (#ia1)readme f README (#ia1)read t bob (#a1)[b][b] f bob (#a1)[b][b]a t bob (#a1)[b]o[b]a f bob (#a1)[c]o[b] t abcd (#a2)XbcX t abcd (#a2)ad t ad (#a2)abcd t abcd (#a2)bd t bd (#a2)abcd t badc (#a2)abcd # This next one is a little tricky: a[d]bc[] = a[]bc[d] t adbc (#a2)abcd f dcba (#a2)abcd # the next one is [d][cb][a] = [a][bc][d] with a transposition t dcba (#a3)abcd t aabaXaaabY (#a1)(a#b)#Y t aabaXaaabY (#a1)(a#b)(a#b)Y t aaXaaaaabY (#a1)(a#b)(a#b)Y t aaaXaaabY (#a1)(a##b)##Y t aaaXbaabY (#a1)(a##b)##Y f read.me (#ia1)README~READ.ME t read.me (#ia1)README~READ_ME f read.me (#ia1)README~(#a1)READ_ME t test *((#s)|/)test((#e)|/)* t test/path *((#s)|/)test((#e)|/)* t path/test *((#s)|/)test((#e)|/)* t path/test/ohyes *((#s)|/)test((#e)|/)* f atest *((#s)|/)test((#e)|/)* f testy *((#s)|/)test((#e)|/)* f testy/path *((#s)|/)test((#e)|/)* f path/atest *((#s)|/)test((#e)|/)* f atest/path *((#s)|/)test((#e)|/)* f path/testy *((#s)|/)test((#e)|/)* f path/testy/ohyes *((#s)|/)test((#e)|/)* f path/atest/ohyes *((#s)|/)test((#e)|/)* t XabcdabcY X(ab|c|d)(#c5)Y t XabcdabcY X(ab|c|d)(#c1,5)Y t XabcdabcY X(ab|c|d)(#c5,8)Y t XabcdabcY X(ab|c|d)(#c4,)Y f XabcdabcY X(ab|c|d)(#c6,)Y f XabcdabcY X(ab|c|d)(#c1,4)Y t ZX Z(|)(#c1)X t froofroo (fro(#c2))(#c2) f froofroofroo (fro(#c2))(#c2) f froofro (fro(#c2))(#c2) t ax ?(#c1,2)x t ax ?(#c1,)x t ax ?(#c0,1)x f ax ?(#c0,0)x f ax ?(#c2,)x t aa a(#c1,2)a t aa a(#c1,)a t aa a(#c0,1)a f aa a(#c0,0)a f aa a(#c2,)a t test.zsh *.?(#c1)sh t test.bash *.?(#c2)sh t test.bash *.?(#c1,2)sh t test.bash *.?(#c1,)sh t test.zsh *.?(#c1,)sh EOT print "$failed tests failed."