OILS / spec / ysh-regex.test.sh View on Github | oils.pub

642 lines, 379 significant
1#### /^.$/
2shopt -s ysh:all
3var pat = ''
4
5setvar pat = /^.$/
6echo pat=$pat
7
8setvar pat = /%start dot %end/
9echo pat=$pat
10
11if ('' ~ pat) { # ERE syntax
12 echo yes
13} else {
14 echo no
15}
16# $pat is same as pat
17if ('f' ~ pat) { # ERE syntax
18 echo yes
19} else {
20 echo no
21}
22
23## STDOUT:
24pat=^.$
25pat=^.$
26no
27yes
28## END
29
30
31#### /.+/
32shopt -s ysh:all
33
34var pat = /.+/
35echo $pat
36
37var s = 'foo'
38if (s ~ pat) { # ERE syntax
39 echo yes
40}
41var empty = ''
42if (empty ~ pat) { echo yes } else { echo no }
43## STDOUT:
44.+
45yes
46no
47## END
48
49#### Repeat {1,3} etc.
50var pat = null
51
52setvar pat = /d{2}/
53echo $pat
54setvar pat = /d{1,3}/
55echo $pat
56setvar pat = /d{1,}/
57echo $pat
58setvar pat = /d{,3}/
59echo $pat
60
61
62## STDOUT:
63[[:digit:]]{2}
64[[:digit:]]{1,3}
65[[:digit:]]{1,}
66[[:digit:]]{,3}
67## END
68
69
70#### d+ digit+ !d+ !digit+
71shopt -s ysh:all
72
73var pat = ''
74
75setvar pat = /d+/
76echo $pat
77if ('42' ~ pat) { echo yes }
78
79var empty = ''
80if (empty ~ pat) { echo yes } else { echo no }
81
82setvar pat = /digit+/
83echo $pat
84setvar pat = /!d+/
85echo $pat
86setvar pat = /!digit+/
87echo $pat
88
89
90## STDOUT:
91[[:digit:]]+
92yes
93no
94[[:digit:]]+
95[^[:digit:]]+
96[^[:digit:]]+
97## END
98
99#### Alternation and sequence
100var pat = ''
101setvar pat = /s d+ | w*/
102echo $pat
103setvar pat = /s d+ or w*/
104echo $pat
105## STDOUT:
106[[:space:]][[:digit:]]+|[[:alpha:][:digit:]_]*
107[[:space:]][[:digit:]]+|[[:alpha:][:digit:]_]*
108## END
109
110#### Char Class Ranges
111shopt -s ysh:all
112
113var pat = ''
114setvar pat = /[0-9 a-f]+/
115echo $pat
116# This is equivalent
117setvar pat = /['0' - '9' 'a' - 'f']+/
118echo $pat
119
120if ('0123' ~ pat) { echo yes } else { echo no }
121if ('zzz' ~ pat) { echo yes } else { echo no }
122if ('' ~ pat) { echo yes } else { echo no }
123## STDOUT:
124[0-9a-f]+
125[0-9a-f]+
126yes
127no
128no
129## END
130
131#### Char Class Set
132shopt -s ysh:all
133var pat = ''
134
135# This is NOT allowed
136# setvar pat = /[a b c]+/
137
138setvar pat = /['abc']+/
139echo $pat
140
141if ('cbcb' ~ pat) { echo yes } else { echo no }
142if ('0123' ~ pat) { echo yes } else { echo no }
143if ('' ~ pat) { echo yes } else { echo no }
144## STDOUT:
145[abc]+
146yes
147no
148no
149## END
150
151#### Range with escaped characters
152shopt -s ysh:all
153
154var pat = null
155
156setvar pat = / [ \x01 - \x0f ] /
157echo $pat | od -A n -t x1
158
159## STDOUT:
160 5b 01 2d 0f 5d 0a
161## END
162
163
164#### Group ()
165shopt -s ysh:all
166var pat = ''
167
168setvar pat = /(%start s or d d)/
169echo $pat
170
171if (' foo' ~ pat) { echo yes } else { echo no }
172if ('-00-' ~ pat) { echo yes } else { echo no }
173if ('foo' ~ pat) { echo yes } else { echo no }
174
175## STDOUT:
176(^[[:space:]]|[[:digit:]][[:digit:]])
177yes
178yes
179no
180## END
181
182#### Capture is acceptable as a group
183shopt -s ysh:all
184var pat = /<capture %start s | d d>/
185echo $pat
186## STDOUT:
187(^[[:space:]]|[[:digit:]][[:digit:]])
188## END
189
190#### literal ''
191shopt -s ysh:all
192var pat = ''
193
194setvar pat = /'abc' 'def'/
195echo $pat
196
197#setvar pat = /'abc' '^ + * ?'/
198#echo $pat
199
200if ('abcde' ~ pat) { echo yes } else { echo no }
201if ('abcdef' ~ pat) { echo yes } else { echo no }
202
203## STDOUT:
204abcdef
205no
206yes
207## END
208
209#### Single quotes and splicing (do what "foo $x ${x}" used to)
210shopt -s ysh:all
211var pat = ''
212
213var x = 'x'
214var y = 'y'
215setvar pat = / @x @x 'abc' @x @y /
216echo $pat
217
218if ('xxabcx' ~ pat) { echo yes } else { echo no }
219if ('xxabcxyf' ~ pat) { echo yes } else { echo no }
220
221## STDOUT:
222xxabcxy
223no
224yes
225## END
226
227#### @splice
228shopt -s ysh:all
229var d = /d+/;
230var ip = / @d '.' @d '.' @d '.' @d /
231echo $ip
232if ('0.0.0.0' ~ ip) { echo yes } else { echo no }
233if ('0.0.0' ~ ip) { echo yes } else { echo no }
234## STDOUT:
235[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+
236yes
237no
238## END
239
240#### splice with capital letters
241shopt -s ysh:all
242var D = /d+/;
243var ip = / D '.' D '.' D '.' D /
244echo $ip
245if ('0.0.0.0' ~ ip) { echo yes } else { echo no }
246if ('0.0.0' ~ ip) { echo yes } else { echo no }
247## STDOUT:
248[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+
249yes
250no
251## END
252
253#### Repeated String Literal With Single Char
254shopt -s ysh:all
255
256var literal = 'f'
257var pat = null
258
259setvar pat = / %start @literal+ %end /
260echo $pat
261setvar pat = / %start (@literal)+ %end /
262echo $pat
263
264if ('fff' ~ pat) { echo yes }
265if ('foo' !~ pat) { echo no }
266
267## STDOUT:
268^f+$
269^(f)+$
270yes
271no
272## END
273
274#### Error when unparenthesized string of more than one character is repeated
275shopt -s ysh:all
276
277var literal = 'foo'
278var pat = null
279
280setvar pat = / %start @literal+ %end /
281echo $pat
282setvar pat = / %start (@literal)+ %end /
283echo $pat
284
285if ('foofoo' ~ pat) { echo yes }
286if ('foof' !~ pat) { echo no }
287
288## status: 1
289## stdout-json: ""
290
291#### Instead of $'foo\\bar' use 'foo' \\ 'bar'
292shopt -s ysh:all
293var pat = /'foo' \\ 'bar'/
294echo $pat
295
296if (r'foo\bar' ~ pat) { echo yes }
297if (r'foo.bar' !~ pat) { echo no }
298## STDOUT:
299foo\\bar
300yes
301no
302## END
303
304#### Negation of Character Class ![a-z]
305shopt -s ysh:all
306
307var pat = / ![ a-z ] /
308echo $pat
309
310if ('0' ~ pat) { echo yes }
311if ('a' !~ pat) { echo no }
312
313## STDOUT:
314[^a-z]
315yes
316no
317## END
318
319#### Posix and Perl class in class literals
320shopt -s ysh:all
321
322var pat = null
323
324setvar pat = / [ space 'z' ] /
325echo $pat
326#setvar pat = / [ ~space 'z' ] /
327#echo $pat
328
329# PROBLEM: can't negate individual POSIX classes. They would have to be a Perl
330# class to be \D or \S.
331# [[:space:]z] negates the whole thing!
332# [^[:space:]]
333
334setvar pat = / [ digit 'z' ] /
335echo $pat
336#setvar pat = / [ ~digit 'z' ] /
337#echo $pat
338
339## STDOUT:
340[[:space:]z]
341[[:digit:]z]
342## END
343
344#### [!d] can't be negated because it's a literal character
345setvar pat = / [ !d 'z' ] /
346echo $pat
347## status: 2
348## stdout-json: ""
349
350#### [!digit] can't be negated in POSIX ERE (but yes in Perl)
351var pat = null
352setvar pat = / [ !digit 'z' ] /
353echo $pat
354## status: 1
355## stdout-json: ""
356
357#### Operator chars in char classes (bash-like)
358
359pat='[-]'
360[[ '-' =~ $pat ]] && echo hyphen
361[[ '\' =~ $pat ]] && echo FAIL
362
363pat='[\]'
364[[ '\' =~ $pat ]] && echo backslash
365[[ '-' =~ $pat ]] && echo FAIL
366
367pat='[]]'
368[[ ']' =~ $pat ]] && echo 'right bracket'
369[[ '[' =~ $pat ]] && echo FAIL
370
371pat='[[]'
372[[ '[' =~ $pat ]] && echo 'left bracket'
373[[ ']' =~ $pat ]] && echo FAIL
374
375pat='[.]'
376[[ '.' =~ $pat ]] && echo period
377[[ '\' =~ $pat ]] && echo FAIL
378
379pat='[\^]'
380[[ '^' =~ $pat ]] && echo caret
381[[ '\' =~ $pat ]] && echo 'no way to have [^]'
382
383## STDOUT:
384hyphen
385backslash
386right bracket
387left bracket
388period
389caret
390no way to have [^]
391## END
392
393#### Operator chars in char classes (eggex)
394shopt --set ysh:upgrade
395
396var pat = / ['-'] /
397#echo PAT=$pat
398if ('-' ~ pat) { echo hyphen }
399if (b'\\' ~ pat) { echo FAIL }
400
401var pat = / [ \\ ] /
402[[ '\' =~ $pat ]] && echo backslash
403[[ '-' =~ $pat ]] && echo FAIL
404
405var pat = / [ ']' ] /
406[[ ']' =~ $pat ]] && echo 'right bracket'
407[[ '[' =~ $pat ]] && echo FAIL
408
409var pat = / [ '[' ] /
410[[ '[' =~ $pat ]] && echo 'left bracket'
411[[ ']' =~ $pat ]] && echo FAIL
412
413var pat = / [ '.' ] /
414[[ '.' =~ $pat ]] && echo period
415[[ '\' =~ $pat ]] && echo FAIL
416
417var pat = / [ \\ '^' ] /
418[[ '^' =~ $pat ]] && echo caret
419[[ '\' =~ $pat ]] && echo 'no way to have [^]'
420
421
422## STDOUT:
423hyphen
424backslash
425right bracket
426left bracket
427period
428caret
429no way to have [^]
430## END
431
432#### Matching ] and \ and ' and " in character classes
433shopt -s ysh:all
434
435# BUG: need C strings in array literal
436var lines = :|
437 'backslash \'
438 'rbracket ]'
439 'lbracket ['
440 "sq '"
441 'dq ""'
442|
443
444# Weird GNU quirk: ] has to come first!
445# []abc] works. But [abc\]] does NOT work. Stupid rule!
446
447var pat = / [ ']' \\ \' \" ] /
448write pat=$pat
449write @lines | egrep $pat
450
451## STDOUT:
452pat=[]'"\\]
453backslash \
454rbracket ]
455sq '
456dq ""
457## END
458
459#### Matching literal hyphen in character classes
460shopt -s ysh:all
461
462var literal = '-'
463var pat = / [ 'a' 'b' @literal ] /
464write pat=$pat
465write 'c-d' 'ab' 'cd' | grep $pat
466## STDOUT:
467pat=[ab-]
468c-d
469ab
470## END
471
472#### Char class special: ^ - ] \
473
474# See demo/ere-char-class-literals.sh
475#
476# \ is special because of gawk
477
478shopt -s ysh:upgrade
479
480
481# Note: single caret disalowed
482var caret = / ['^' 'x'] /
483echo caret=$caret
484
485var caret2 = / [ \x5e 'x'] /
486echo caret2=$caret2
487
488var caret3 = / [ \u{5e} 'x'] /
489echo caret3=$caret3
490
491if ('x' ~ caret3) {
492 echo 'match x'
493}
494if ('^' ~ caret3) {
495 echo 'match ^'
496}
497
498echo ---
499
500var hyphen = / ['a' '-' 'b'] /
501echo hyphen=$hyphen
502
503var hyphen2 = / ['a' \x2d 'b' ] /
504echo hyphen2=$hyphen2
505
506if ('-' ~ hyphen2) {
507 echo 'match -'
508}
509
510if ('a' ~ hyphen2) {
511 echo 'match a'
512}
513
514if ('c' ~ hyphen2) {
515 echo 'match c'
516}
517
518echo ---
519
520var rbracket = / [ '[' ']' ] /
521echo rbracket=$rbracket
522
523var rbracket2 = / [ \x5b \x5d ] /
524echo rbracket2=$rbracket2
525
526if ('[' ~ rbracket2) {
527 echo 'match ['
528}
529
530if (']' ~ rbracket2) {
531 echo 'match ]'
532}
533
534echo ---
535
536var backslash = / [ 'x' \\ 'n' ] /
537echo backslash=$backslash
538
539var backslash2 = / [ 'x' \x5c 'n' ] /
540echo backslash2=$backslash2
541
542var backslash3 = / [ 'x' $'\\' 'n' ] /
543echo backslash3=$backslash3
544
545if ('x' ~ backslash3) {
546 echo 'match x'
547}
548
549if ('n' ~ backslash3) {
550 echo 'match n'
551}
552
553if (b'\\' ~ backslash3) {
554 echo 'match backslash'
555}
556
557if ($'\n' ~ backslash3) {
558 echo 'match nnewline'
559}
560
561
562## STDOUT:
563caret=[x^]
564caret2=[x^]
565caret3=[x^]
566match x
567match ^
568---
569hyphen=[ab-]
570hyphen2=[ab-]
571match -
572match a
573---
574rbracket=[][]
575rbracket2=[][]
576match [
577match ]
578---
579backslash=[xn\\]
580backslash2=[xn\\]
581backslash3=[xn\\]
582match x
583match n
584match backslash
585## END
586
587
588#### character class with digit [\\0] should not crash (issue #2380)
589shopt -s ysh:all
590
591var pat = /[\\0]/
592echo "pattern: $pat"
593
594# Test matching
595pp test_ ('0' ~ pat)
596pp test_ ('1' ~ pat)
597pp test_ (b'\\' ~ pat)
598
599echo ---
600
601# Also test other digits in character class
602var digits = /[0-9]/
603echo $digits
604pp test_ ('5' ~ digits)
605pp test_ ('x' ~ digits)
606
607
608## STDOUT:
609pattern: [0\\]
610(Bool) true
611(Bool) false
612(Bool) true
613---
614[0-9]
615(Bool) true
616(Bool) false
617## END
618
619#### Multiple digits like [25] are invalid
620
621# synonyms
622var pat = /[2 5]/
623echo $pat
624var pat = /[2 '5']/
625echo $pat
626
627var pat = /[25]/
628echo $pat
629
630## status: 2
631## STDOUT:
632[25]
633[25]
634## END
635
636#### Negation of digit not allowed
637
638var digits = /[!2]/
639
640## status: 2
641## STDOUT:
642## END