1 # Test out Oil's regular expression syntax.
2
3 #### /^.$/
4 shopt -s oil:all
5 var pat = ''
6
7 setvar pat = /^.$/
8 echo pat=$pat
9
10 setvar pat = /%start dot %end/
11 echo pat=$pat
12
13 if ('' ~ pat) { # ERE syntax
14 echo yes
15 } else {
16 echo no
17 }
18 # $pat is same as pat
19 if ('f' ~ pat) { # ERE syntax
20 echo yes
21 } else {
22 echo no
23 }
24
25 ## STDOUT:
26 pat=^.$
27 pat=^.$
28 no
29 yes
30 ## END
31
32
33 #### /.+/
34 shopt -s oil:all
35
36 var pat = /.+/
37 echo $pat
38
39 var s = 'foo'
40 if (s ~ pat) { # ERE syntax
41 echo yes
42 }
43 var empty = ''
44 if (empty ~ pat) { echo yes } else { echo no }
45 ## STDOUT:
46 .+
47 yes
48 no
49 ## END
50
51 #### Positional captures with _match
52 shopt -s oil:all
53
54 var x = 'zz 2020-08-20'
55
56 if [[ $x =~ ([[:digit:]]+)-([[:digit:]]+) ]] {
57 argv.py "${BASH_REMATCH[@]}"
58 }
59
60 # THIS IS A NO-OP. The variable is SHADOWED by the special name.
61 # I think that's OK.
62 setvar BASH_REMATCH = %(reset)
63
64 if (x ~ /<d+> '-' <d+>/) {
65 argv.py "${BASH_REMATCH[@]}"
66 argv.py $_match(0) $_match(1) $_match(2)
67
68 argv.py $_match() # synonym for _match(0)
69
70 # TODO: Also test _start() and _end()
71 }
72 ## STDOUT:
73 ['2020-08', '2020', '08']
74 ['2020-08', '2020', '08']
75 ['2020-08', '2020', '08']
76 ['2020-08']
77 ## END
78
79 #### s ~ regex and s !~ regex
80 shopt -s oil:upgrade
81
82 var s = 'foo'
83 if (s ~ '.([[:alpha:]]+)') { # ERE syntax
84 echo matches
85 argv.py $_match(0) $_match(1)
86 }
87 if (s !~ '[[:digit:]]+') {
88 echo "does not match"
89 argv.py $_match(0) $_match(1)
90 }
91
92 if (s ~ '[[:digit:]]+') {
93 echo "matches"
94 }
95 # Should be cleared now
96 # should this be Undef rather than ''?
97 var x = _match(0)
98 var y = _match(1)
99 if (x === null and y === null) {
100 echo 'cleared'
101 }
102
103 ## STDOUT:
104 matches
105 ['foo', 'oo']
106 does not match
107 ['foo', 'oo']
108 cleared
109 ## END
110
111 #### _start() and _end()
112 shopt -s oil:upgrade
113
114 var s = 'foo123bar'
115 if (s ~ /digit+/) {
116 echo start=$_start() end=$_end()
117 }
118
119 if (s ~ / word+ <digit+> /) {
120 echo start=$_start(1) end=$_end(1)
121 }
122 ## STDOUT:
123 start=3 end=6
124 start=3 end=6
125 ## END
126
127 #### Repeat {1,3} etc.
128 var pat = null
129
130 setvar pat = /d{2}/
131 echo $pat
132 setvar pat = /d{1,3}/
133 echo $pat
134 setvar pat = /d{1,}/
135 echo $pat
136 setvar pat = /d{,3}/
137 echo $pat
138
139
140 ## STDOUT:
141 [[:digit:]]{2}
142 [[:digit:]]{1,3}
143 [[:digit:]]{1,}
144 [[:digit:]]{,3}
145 ## END
146
147
148 #### d+ digit+ !d+ !digit+
149 shopt -s oil:all
150
151 var pat = ''
152
153 setvar pat = /d+/
154 echo $pat
155 if ('42' ~ pat) { echo yes }
156
157 var empty = ''
158 if (empty ~ pat) { echo yes } else { echo no }
159
160 setvar pat = /digit+/
161 echo $pat
162 setvar pat = /!d+/
163 echo $pat
164 setvar pat = /!digit+/
165 echo $pat
166
167
168 ## STDOUT:
169 [[:digit:]]+
170 yes
171 no
172 [[:digit:]]+
173 [^[:digit:]]+
174 [^[:digit:]]+
175 ## END
176
177 #### Alternation and sequence
178 var pat = ''
179 setvar pat = /s d+ | w*/
180 echo $pat
181 setvar pat = /s d+ or w*/
182 echo $pat
183 ## STDOUT:
184 [[:space:]][[:digit:]]+|[[:alpha:][:digit:]_]*
185 [[:space:]][[:digit:]]+|[[:alpha:][:digit:]_]*
186 ## END
187
188 #### Char Class Ranges
189 shopt -s oil:all
190
191 var pat = ''
192 setvar pat = /[0-9 a-f]+/
193 echo $pat
194 # This is equivalent
195 setvar pat = /['0' - '9' 'a' - 'f']+/
196 echo $pat
197
198 if ('0123' ~ pat) { echo yes } else { echo no }
199 if ('zzz' ~ pat) { echo yes } else { echo no }
200 if ('' ~ pat) { echo yes } else { echo no }
201 ## STDOUT:
202 [0-9a-f]+
203 [0-9a-f]+
204 yes
205 no
206 no
207 ## END
208
209 #### Char Class Set
210 shopt -s oil:all
211 var pat = ''
212
213 # This is NOT allowed
214 # setvar pat = /[a b c]+/
215
216 setvar pat = /['abc']+/
217 echo $pat
218
219 if ('cbcb' ~ pat) { echo yes } else { echo no }
220 if ('0123' ~ pat) { echo yes } else { echo no }
221 if ('' ~ pat) { echo yes } else { echo no }
222 ## STDOUT:
223 [abc]+
224 yes
225 no
226 no
227 ## END
228
229 #### Range with escaped characters
230 shopt -s oil:all
231
232 var pat = null
233
234 setvar pat = / [ \x00 - \x0f ] /
235 echo $pat | od -A n -t x1
236
237 ## STDOUT:
238 5b 00 2d 0f 5d 0a
239 ## END
240
241
242 #### Group ()
243 shopt -s oil:all
244 var pat = ''
245
246 setvar pat = /(%start s or d d)/
247 echo $pat
248
249 if (' foo' ~ pat) { echo yes } else { echo no }
250 if ('-00-' ~ pat) { echo yes } else { echo no }
251 if ('foo' ~ pat) { echo yes } else { echo no }
252
253 ## STDOUT:
254 (^[[:space:]]|[[:digit:]][[:digit:]])
255 yes
256 yes
257 no
258 ## END
259
260 #### Capture is acceptable as a group
261 shopt -s oil:all
262 var pat = /<%start s | d d>/
263 echo $pat
264 ## STDOUT:
265 (^[[:space:]]|[[:digit:]][[:digit:]])
266 ## END
267
268 #### Named captures with _match
269 shopt -s oil:all
270
271 var x = 'zz 2020-08-20'
272
273 if (x ~ /<d+ : year> '-' <d+ : month>/) {
274 argv.py $_match('year') $_match('month')
275 }
276 ## STDOUT:
277 ['2020', '08']
278 ## END
279
280 #### Named Capture Decays Without Name
281 shopt -s oil:all
282 var pat = /<d+ : month>/
283 echo $pat
284
285 if ('123' ~ pat) {
286 echo yes
287 }
288
289 ## STDOUT:
290 ([[:digit:]]+)
291 yes
292 ## END
293
294 #### Named Capture With ~ Assigns Variable
295 shopt -s oil:all
296 var pat = /<d+ : month>/
297 echo $pat
298
299 if ('123' ~ pat) {
300 echo yes
301 = month
302 }
303 ## STDOUT:
304 ([[:digit:]]+)
305 yes
306 TODO MONTH
307 ## END
308
309 #### literal ''
310 shopt -s oil:all
311 var pat = ''
312
313 setvar pat = /'abc' 'def'/
314 echo $pat
315
316 #setvar pat = /'abc' '^ + * ?'/
317 #echo $pat
318
319 if ('abcde' ~ pat) { echo yes } else { echo no }
320 if ('abcdef' ~ pat) { echo yes } else { echo no }
321
322 ## STDOUT:
323 abcdef
324 no
325 yes
326 ## END
327
328 #### double quoted, $x, and ${x}
329 shopt -s oil:all
330 var pat = ''
331
332 var x = 'x'
333 var y = 'y'
334 setvar pat = / $x ${x} "abc" "$x${y}"/
335 echo $pat
336
337 if ('xxabcx' ~ pat) { echo yes } else { echo no }
338 if ('xxabcxyf' ~ pat) { echo yes } else { echo no }
339
340 ## STDOUT:
341 xxabcxy
342 no
343 yes
344 ## END
345
346 #### @splice
347 shopt -s oil:all
348 var d = /d+/;
349 var ip = / @d '.' @d '.' @d '.' @d /
350 echo $ip
351 if ('0.0.0.0' ~ ip) { echo yes } else { echo no }
352 if ('0.0.0' ~ ip) { echo yes } else { echo no }
353 ## STDOUT:
354 [[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+
355 yes
356 no
357 ## END
358
359 #### splice with capital letters
360 shopt -s oil:all
361 var D = /d+/;
362 var ip = / D '.' D '.' D '.' D /
363 echo $ip
364 if ('0.0.0.0' ~ ip) { echo yes } else { echo no }
365 if ('0.0.0' ~ ip) { echo yes } else { echo no }
366 ## STDOUT:
367 [[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+
368 yes
369 no
370 ## END
371
372 #### Matching escaped tab character
373 shopt -s oil:all
374
375 var lines=%($'aa\tbb' $'cc\tdd')
376
377 var pat = / ('a' [\t] 'b') /
378 write pat=$pat
379 write @lines | egrep $pat
380
381 ## stdout-json: "pat=(a[\t]b)\naa\tbb\n"
382
383 #### Match unicode char
384 shopt -s oil:all
385 var pat = / 'a' dot 'b' /
386
387 if ('axb' ~ pat ) { echo yes } else { echo no }
388
389 # mu character
390 if ($'a\xce\xbcb' ~ pat ) { echo yes } else { echo no }
391
392 if ('aZZb' ~ pat ) { echo yes } else { echo no }
393 ## STDOUT:
394 yes
395 yes
396 no
397 ## END
398
399 #### Match non-ASCII byte denoted using $'\xff' (TODO: LANG=C)
400
401 # NOTE: This pattern doesn't work with en_US.UTF-8. I think the user should
402 # set LANG=C or shopt --unset libc_utf8.
403
404 shopt -s oil:all
405 var pat = /[ $'\xff' ]/;
406
407 echo $pat | od -A n -t x1
408 if ($'\xff' ~ pat) { echo yes } else { echo no }
409 if ($'\xfe' ~ pat) { echo yes } else { echo no }
410
411 ## STDOUT:
412 5b ff 5d 0a
413 yes
414 no
415 ## END
416
417 #### Match non-ASCII byte denoted using \xff
418 shopt -s oil:all
419 var pat = /[ \xff ]/;
420
421 # Show what it translates to
422 echo $pat | od -A n -t x1
423
424 # TODO: This might require LANG=C to work
425 #if ($'\xff' ~ pat) { echo yes } else { echo no }
426 #if ($'\xfe' ~ pat) { echo yes } else { echo no }
427
428 ## STDOUT:
429 5b ff 5d 0a
430 ## END
431
432 #### ERE can express Unicode escapes that are in the ASCII range
433 shopt -s oil:all
434 var pat = /[ \u{7f} ]/;
435
436 echo $pat | od -A n -t x1
437 if ($'\x7f' ~ pat) { echo yes } else { echo no }
438 if ($'\x7e' ~ pat) { echo yes } else { echo no }
439
440 var pat2 = /[ \u{7f} ]/;
441 var pat3 = /[ \u{0007f} ]/;
442 test "$pat2" = "$pat3" && echo 'equal'
443
444 var range = / [ \u{70} - \u{7f} ] /
445 if ($'\x70' ~ range) { echo yes } else { echo no }
446 if ($'\x69' ~ range) { echo yes } else { echo no }
447
448 ## STDOUT:
449 5b 7f 5d 0a
450 yes
451 no
452 equal
453 yes
454 no
455 ## END
456
457 #### ERE can't express higher Unicode escapes
458 shopt -s oil:all
459 var pat2 = /[ \u{00} - \u{ff} ]/;
460 = pat2
461 var pat1 = /[ \u{ff} ]/;
462
463 echo $pat1 | od -A n -t x1
464 if ($'\x7f' ~ pat) { echo yes } else { echo no }
465 if ($'\x7e' ~ pat) { echo yes } else { echo no }
466
467 ## status: 1
468 ## stdout-json: ""
469
470 #### non-ASCII bytes must be singleton terms, e.g. '\x7f\xff' is disallowed
471 var bytes = $'\x7f\xff'
472 var pat = / [ $bytes ] /
473 echo $pat
474 ## status: 1
475 ## stdout-json: ""
476
477 #### Matching escaped tab character
478 shopt -s oil:all
479
480 # BUG: need C strings in array literal
481 var lines=%($'aa\tbb' $'cc\tdd')
482
483 var pat = / ('a' [\t] 'b') /
484 write pat=$pat
485 write @lines | egrep $pat
486
487 ## stdout-json: "pat=(a[\t]b)\naa\tbb\n"
488
489 #### Repeated String Literal With Single Char
490 shopt -s oil:all
491
492 var literal = 'f'
493 var pat = null
494
495 setvar pat = / %start $literal+ %end /
496 echo $pat
497 setvar pat = / %start ($literal)+ %end /
498 echo $pat
499
500 if ('fff' ~ pat) { echo yes }
501 if ('foo' !~ pat) { echo no }
502
503 ## STDOUT:
504 ^f+$
505 ^(f)+$
506 yes
507 no
508 ## END
509
510 #### Error when unparenthesized string of more than one character is repeated
511 shopt -s oil:all
512
513 var literal = 'foo'
514 var pat = null
515
516 setvar pat = / %start $literal+ %end /
517 echo $pat
518 setvar pat = / %start ($literal)+ %end /
519 echo $pat
520
521 if ('foofoo' ~ pat) { echo yes }
522 if ('foof' !~ pat) { echo no }
523
524 ## status: 1
525 ## stdout-json: ""
526
527 #### Instead of $'foo\\bar' use 'foo' \\ 'bar'
528 shopt -s oil:all
529 var pat = /'foo' \\ 'bar'/
530 echo $pat
531
532 if (r'foo\bar' ~ pat) { echo yes }
533 if (r'foo.bar' !~ pat) { echo no }
534 ## STDOUT:
535 foo\\bar
536 yes
537 no
538 ## END
539
540 #### Negation of Character Class ![a-z]
541 shopt -s oil:all
542
543 var pat = / ![ a-z ] /
544 echo $pat
545
546 if ('0' ~ pat) { echo yes }
547 if ('a' !~ pat) { echo no }
548
549 ## STDOUT:
550 [^a-z]
551 yes
552 no
553 ## END
554
555 #### Posix and Perl class in class literals
556 shopt -s oil:all
557
558 var pat = null
559
560 setvar pat = / [ space 'z' ] /
561 echo $pat
562 #setvar pat = / [ ~space 'z' ] /
563 #echo $pat
564
565 # PROBLEM: can't negate individual POSIX classes. They would have to be a Perl
566 # class to be \D or \S.
567 # [[:space:]z] negates the whole thing!
568 # [^[:space:]]
569
570 setvar pat = / [ digit 'z' ] /
571 echo $pat
572 #setvar pat = / [ ~digit 'z' ] /
573 #echo $pat
574
575 ## STDOUT:
576 [[:space:]z]
577 [[:digit:]z]
578 ## END
579
580 #### [!d] can't be negated because it's a literal character
581 setvar pat = / [ !d 'z' ] /
582 echo $pat
583 ## status: 2
584 ## stdout-json: ""
585
586 #### [!digit] can't be negated in POSIX ERE (but yes in Perl)
587 var pat = null
588 setvar pat = / [ !digit 'z' ] /
589 echo $pat
590 ## status: 1
591 ## stdout-json: ""
592
593 #### Long Python Example
594
595 # https://docs.python.org/3/reference/lexical_analysis.html#integer-literals
596
597 # integer ::= decinteger | bininteger | octinteger | hexinteger
598 # decinteger ::= nonzerodigit (["_"] digit)* | "0"+ (["_"] "0")*
599 # bininteger ::= "0" ("b" | "B") (["_"] bindigit)+
600 # octinteger ::= "0" ("o" | "O") (["_"] octdigit)+
601 # hexinteger ::= "0" ("x" | "X") (["_"] hexdigit)+
602 # nonzerodigit ::= "1"..."9"
603 # digit ::= "0"..."9"
604 # bindigit ::= "0" | "1"
605 # octdigit ::= "0"..."7"
606 # hexdigit ::= digit | "a"..."f" | "A"..."F"
607
608 shopt -s oil:all
609
610 const DecDigit = / [0-9] /
611 const BinDigit = / [0-1] /
612 const OctDigit = / [0-7] /
613 const HexDigit = / [0-9 a-f A-F] / # note: not splicing Digit into character class
614
615 const DecInt = / [1-9] ('_'? DecDigit)* | '0'+ ('_'? '0')* /
616 const BinInt = / '0' [b B] ('_'? BinDigit)+ /
617 const OctInt = / '0' [o O] ('_'? OctDigit)+ /
618 const HexInt = / '0' [x X] ('_'? HexDigit)+ /
619
620 const Integer = / %start (DecInt | BinInt | OctInt | HexInt) %end /
621
622 #echo $Integer
623
624 if ( '123' ~ Integer) { echo 'Y' }
625 if ( 'zzz' !~ Integer) { echo 'N' }
626
627 if ('123_000' ~ Integer) { echo 'Y decimal' }
628 if ('000_123' !~ Integer) { echo 'N decimal' }
629
630 if ( '0b100' ~ Integer) { echo 'Y binary' }
631 if ( '0b102' !~ Integer) { echo 'N binary' }
632
633 if ( '0o755' ~ Integer) { echo 'Y octal' }
634 if ( '0o778' !~ Integer) { echo 'N octal' }
635
636 if ( '0xFF' ~ Integer) { echo 'Y hex' }
637 if ( '0xFG' !~ Integer) { echo 'N hex' }
638
639 ## STDOUT:
640 Y
641 N
642 Y decimal
643 N decimal
644 Y binary
645 N binary
646 Y octal
647 N octal
648 Y hex
649 N hex
650 ## END
651
652 #### Invalid sh operation on eggex
653 var pat = / d+ /
654 #pat[invalid]=1
655 pat[invalid]+=1
656 ## status: 1
657 ## stdout-json: ""
658
659
660 #### Regex in a loop (bug regression)
661
662 shopt --set oil:all
663
664 var content = [ 1, 2 ]
665 var i = 0
666 while (i < len(content)) {
667 var line = content[i]
668 write $[content[i]]
669 if (Str(line) ~ / s* 'imports' s* '=' s* .* /) {
670 exit
671 }
672 setvar i += 1
673 }
674
675 ## STDOUT:
676 1
677 2
678 ## END
679
680
681 #### Regex in a loop depending on var
682
683 shopt --set oil:all
684
685 var lines = ['foo', 'bar']
686 for line in (lines) {
687 write "line $line"
688
689 # = / $line /
690
691 if ("x$line" ~ / dot $line /) {
692 #if (line ~ / $line /) {
693 write "matched $line"
694 }
695 }
696
697 ## STDOUT:
698 line foo
699 matched foo
700 line bar
701 matched bar
702 ## END
703
704
705 #### Regex with [ (bug regression)
706 shopt --set oil:all
707
708 if ('[' ~ / "[" /) {
709 echo 'dq'
710 }
711
712 if ('[' ~ / '[' /) {
713 echo 'sq'
714 }
715
716 if ('[' ~ / [ '[' ] /) {
717 echo 'char class'
718 }
719
720 # User-reported string
721 if ("a" ~ / s* 'imports' s* '=' s* '[' /) {
722 echo "yes"
723 }
724
725 ## STDOUT:
726 dq
727 sq
728 char class
729 ## END
730
731 #### Operator chars in char classes (bash-like)
732
733 pat='[-]'
734 [[ '-' =~ $pat ]] && echo hyphen
735 [[ '\' =~ $pat ]] && echo FAIL
736
737 pat='[\]'
738 [[ '\' =~ $pat ]] && echo backslash
739 [[ '-' =~ $pat ]] && echo FAIL
740
741 pat='[]]'
742 [[ ']' =~ $pat ]] && echo 'right bracket'
743 [[ '[' =~ $pat ]] && echo FAIL
744
745 pat='[[]'
746 [[ '[' =~ $pat ]] && echo 'left bracket'
747 [[ ']' =~ $pat ]] && echo FAIL
748
749 pat='[.]'
750 [[ '.' =~ $pat ]] && echo period
751 [[ '\' =~ $pat ]] && echo FAIL
752
753 pat='[\^]'
754 [[ '^' =~ $pat ]] && echo caret
755 [[ '\' =~ $pat ]] && echo 'no way to have [^]'
756
757 ## STDOUT:
758 hyphen
759 backslash
760 right bracket
761 left bracket
762 period
763 caret
764 no way to have [^]
765 ## END
766
767 #### Operator chars in char classes (eggex)
768 shopt --set oil:upgrade
769
770 var pat = / ['-'] /
771 #echo PAT=$pat
772 if ('-' ~ pat) { echo hyphen }
773 if ($'\\' ~ pat) { echo FAIL }
774
775 var pat = / [ \\ ] /
776 [[ '\' =~ $pat ]] && echo backslash
777 [[ '-' =~ $pat ]] && echo FAIL
778
779 var pat = / [ ']' ] /
780 [[ ']' =~ $pat ]] && echo 'right bracket'
781 [[ '[' =~ $pat ]] && echo FAIL
782
783 var pat = / [ '[' ] /
784 [[ '[' =~ $pat ]] && echo 'left bracket'
785 [[ ']' =~ $pat ]] && echo FAIL
786
787 var pat = / [ '.' ] /
788 [[ '.' =~ $pat ]] && echo period
789 [[ '\' =~ $pat ]] && echo FAIL
790
791 var pat = / [ \\ '^' ] /
792 [[ '^' =~ $pat ]] && echo caret
793 [[ '\' =~ $pat ]] && echo 'no way to have [^]'
794
795
796 ## STDOUT:
797 hyphen
798 backslash
799 right bracket
800 left bracket
801 period
802 caret
803 no way to have [^]
804 ## END
805
806 #### Matching ] and \ and ' and " in character classes
807 shopt -s oil:all
808
809 # BUG: need C strings in array literal
810 var lines=%(
811 'backslash \'
812 'rbracket ]'
813 'lbracket ['
814 "sq '"
815 'dq "'
816 )
817
818 # Weird GNU quirk: ] has to come first!
819 # []abc] works. But [abc\]] does NOT work. Stupid rule!
820
821 var pat = / [ ']' \\ \' \" ] /
822 write pat=$pat
823 write @lines | egrep $pat
824
825 ## STDOUT:
826 pat=[]'"\\]
827 backslash \
828 rbracket ]
829 sq '
830 dq "
831 ## END
832
833 #### Matching literal hyphen in character classes
834 shopt -s oil:all
835
836 var literal = '-'
837 var pat = / [ 'a' 'b' $literal ] /
838 write pat=$pat
839 write 'c-d' 'ab' 'cd' | grep $pat
840 ## STDOUT:
841 pat=[ab-]
842 c-d
843 ab
844 ## END
845
846 #### Char class special: ^ - ] \
847
848 # See demo/ere-char-class-literals.sh
849 #
850 # \ is special because of gawk
851
852 shopt -s oil:upgrade
853
854
855 # Note: single caret disalowed
856 var caret = / ['^' 'x'] /
857 echo caret=$caret
858
859 var caret2 = / [ \x5e 'x'] /
860 echo caret2=$caret2
861
862 var caret3 = / [ \u{5e} 'x'] /
863 echo caret3=$caret3
864
865 if ('x' ~ caret3) {
866 echo 'match x'
867 }
868 if ('^' ~ caret3) {
869 echo 'match ^'
870 }
871
872 echo ---
873
874 var hyphen = / ['a' '-' 'b'] /
875 echo hyphen=$hyphen
876
877 var hyphen2 = / ['a' \x2d 'b' ] /
878 echo hyphen2=$hyphen2
879
880 if ('-' ~ hyphen2) {
881 echo 'match -'
882 }
883
884 if ('a' ~ hyphen2) {
885 echo 'match a'
886 }
887
888 if ('c' ~ hyphen2) {
889 echo 'match c'
890 }
891
892 echo ---
893
894 var rbracket = / [ '[' ']' ] /
895 echo rbracket=$rbracket
896
897 var rbracket2 = / [ \x5b \x5d ] /
898 echo rbracket2=$rbracket2
899
900 if ('[' ~ rbracket2) {
901 echo 'match ['
902 }
903
904 if (']' ~ rbracket2) {
905 echo 'match ]'
906 }
907
908 echo ---
909
910 var backslash = / [ 'x' \\ 'n' ] /
911 echo backslash=$backslash
912
913 var backslash2 = / [ 'x' \x5c 'n' ] /
914 echo backslash2=$backslash2
915
916 var backslash3 = / [ 'x' $'\\' 'n' ] /
917 echo backslash3=$backslash3
918
919 if ('x' ~ backslash3) {
920 echo 'match x'
921 }
922
923 if ('n' ~ backslash3) {
924 echo 'match n'
925 }
926
927 if ($'\\' ~ backslash3) {
928 echo 'match backslash'
929 }
930
931 if ($'\n' ~ backslash3) {
932 echo 'match nnewline'
933 }
934
935
936 ## STDOUT:
937 caret=[x^]
938 caret2=[x^]
939 caret3=[x^]
940 match x
941 match ^
942 ---
943 hyphen=[ab-]
944 hyphen2=[ab-]
945 match -
946 match a
947 ---
948 rbracket=[][]
949 rbracket2=[][]
950 match [
951 match ]
952 ---
953 backslash=[xn\\]
954 backslash2=[xn\\]
955 backslash3=[xn\\]
956 match x
957 match n
958 match backslash
959 ## END
960