A Racket string is a sequence of Unicode characters (code points, not bytes), and strings are indexed by character: (string-ref "naïve" 2) is #\ï. Regular expressions match text in strings, byte strings and ports. This page lists the string functions, then the regular-expression language and its functions.
Characters
The predicates of racket/base are char-alphabetic?, char-numeric?, char-whitespace?, char-blank?, char-upper-case?, char-lower-case?, char-title-case?, char-symbolic?, char-punctuation?, char-graphic?, char-iso-control? and char-extended-pictographic?, all following Unicode properties. char-upcase, char-downcase, char-titlecase and char-foldcase convert case; char->integer and integer->char convert to and from the code point; char-general-category gives the Unicode category as a symbol; char-utf-8-length the number of bytes. The comparison functions are char=?, char<?, char<=?, char>?, char>=? and the case-insensitive char-ci=? and its relatives. Literals are described on Lexical structure.
Strings
| Group | Functions |
|---|---|
| Construct | make-string, string, string-copy, build-string, string-append, string-append*, string-append-immutable, list->string, string->immutable-string, (~a …) |
| Select | string-length, string-ref, substring, string->list, string-copy! |
| Mutate | string-set!, string-fill!, string-copy! (only on mutable strings; a literal is immutable) |
| Compare | string=?, string<?, string<=?, string>?, string>=? and the -ci versions (case-insensitive); the string-locale versions compare by the current locale |
| Case and normal form | string-upcase, string-downcase, string-titlecase, string-foldcase, string-normalize-nfc, -nfd, -nfkc, -nfkd, string-locale-upcase, string-locale-downcase |
| Grapheme clusters | string-grapheme-span and string-grapheme-count count what a reader sees as one character, however many code points it takes |
racket/string | string-join ((string-join '("a" "b") ", ")), string-split (by white space by default, or by a separator, with #:trim? and #:repeat?), string-trim, string-replace (#:all? defaults to true), string-normalize-spaces, string-prefix?, string-suffix?, string-contains?, string-find, non-empty-string? |
| Convert | number->string, string->number (returns #f if it does not parse), string->symbol, symbol->string, string->bytes/utf-8, bytes->string/utf-8, string->path, string->keyword, string->list, ~a, ~s, ~r |
Two strings that read alike are not necessarily eq?; use string=? or equal?. A string that came from a literal or from string->immutable-string is immutable, and an attempt to string-set! one raises an error.
Regular expression syntax
A regular expression is a value (regexp?), written as a literal #rx"…" or #px"…" or made with (regexp str) or (pregexp str); byte-regexp and byte-pregexp make ones that match bytes. A regexp (#rx) is the simpler dialect; a pregexp (#px) is the Perl-style dialect with more escapes and bounded repetition. Because the pattern is a string, every backslash of the pattern is doubled in source: #px"\\d+".
The core, shared by both dialects
| Syntax | Matches |
|---|---|
a|b | either, trying the left first |
ab | the first, then the second |
a*, a+, a? | 0 or more, 1 or more, 0 or 1 times, as many as possible; a trailing ? (a*?, a+?, a??) makes it as few as possible |
(r) | the sub-expression r, and reports it as a numbered group |
(?:r) – written (?Mode:r) with an empty mode | the sub-expression without reporting it |
[…], [^…] | one character in, or not in, a set: a literal, a range a-f, or (in #px) a class. A ] first in the set, or a - first or last, is literal |
. | any character (except a newline in multi mode) |
^, $ | the start and the end of the input (in multi mode, of each line) |
(?i:r), (?-i:r), (?s:r), (?-s:r), (?m:r), (?-m:r), and combinations | r in a mode: i case-insensitive, s not in multi mode (so . matches newline), m multi mode (^ and $ match at lines; . not newline); the - turns a mode off |
(?>r) | only the first way r can match, without trying others (an atomic group) |
(?=r), (?!r), (?<=r), (?<!r) | look-ahead and look-behind: match the empty string if r matches (or does not match) after (or before) this point. A look-behind pattern must match a bounded length |
(?(n)p|q), (?(?=r)p|q), (?(n)p) | conditional: the first pattern if group n has matched (or the look is true), else the second (or the empty match) |
a literal character, or \c in #rx | that character; in a #rx a \ before any character makes it literal |
Only in #px
| Syntax | Matches |
|---|---|
a{n}, a{n,}, a{,m}, a{n,m}, a{} | exactly n; n or more; up to m; between; zero or more times. { and } are literal in #rx |
\n (a digit) | the same text as the nth group matched (a back-reference) |
\d \D | a digit 0-9; anything else |
\w \W | a letter, digit or _ (ASCII); anything else |
\s \S | space, tab, newline, form feed, return; anything else |
\b \B | a word boundary; a place that is not one |
\p{Property} \P{Property} | a character (a valid UTF-8 encoding) in, or not in, a Unicode category such as Ll; \p{^Ll} negates inside. The categories are Ll Lu Lt Lm L& Lo L Nd Nl No N Ps Pe Pi Pf Pc Pd Po P Mn Mc Me M Sc Sk Sm So S Zl Zp Zs Z Cc Cf Cs Cn Co C and . for all |
\X | a grapheme cluster (added in 8.15.0.8) |
[[:alpha:]] and the other POSIX classes | inside a set: alpha upper lower digit xdigit alnum word blank space graph print cntrl ascii |
\d, \w, \s and the other classes inside […]; \c for a non-letter, non-digit character | classes work inside a set; a backslash makes a non-alphanumeric character literal, in or out of a set |
Two rules are checked syntactically: the thing repeated by *, + or {…} must not be able to match the empty string (so (a*)* is rejected), and a look-behind must match a bounded number of characters. In case-insensitive mode a back-reference is case-insensitive for ASCII only. A . in a character regexp applied to bytes or a port matches only a valid UTF-8 encoding; in a byte regexp it matches any byte.
Matching and replacing
The pattern argument of these functions may be a regexp value, a byte regexp, or a string or byte string (compiled each time). The input may be a string, bytes, a path or an input port; with an input port the match reads from the stream.
| Function | Returns |
|---|---|
(regexp-match pat input [start end out prefix]) | #f, or a list of the whole match followed by each group (a group that did not match is #f); strings if the input is a string and the pattern is not a byte regexp, bytes otherwise |
(regexp-match* pat input #:match-select …) | a list of all non-overlapping matches (or of a chosen group, or of all of them as lists) |
(regexp-match? pat input), (regexp-match-exact? pat input) | a boolean: whether it matches somewhere; whether the whole input matches |
(regexp-match-positions pat input), regexp-match-positions* | the pairs of start and end indices instead of strings |
regexp-try-match, regexp-match-peek, regexp-match-peek-positions, regexp-match-peek-immediate, regexp-match/end | variants for ports: without consuming, and with the bytes before the end of the match |
(regexp-split pat input) | the pieces of the input between matches |
(regexp-replace pat input insert), regexp-replace*, regexp-replaces | the input with the first match, every match, or several patterns in turn replaced |
(regexp-quote str), (regexp-replace-quote str) | escape a string so that it matches itself in a pattern, or inserts itself in a replacement |
(regexp-max-lookbehind pat), (regexp-capture-group-count pat) | facts about a compiled pattern |
The insert string
In regexp-replace the third argument is a string or a procedure. A string may contain & or \0 (the whole match), \1, \2 … (the groups; an unused group is the empty string), \& for a literal &, \\ for a backslash, and \$ for nothing (to end a number: "\\1\\$0"); a backslash before anything else counts as \0. A procedure is called with the whole match and the groups as strings and returns the replacement.
#lang racket
(regexp-match #px"(\\d+)-(\\d+)" "tel 555-1234 ok") ; '("555-1234" "555" "1234")
(regexp-match* #rx"[a-z]+" "ab, cd; ef") ; '("ab" "cd" "ef")
(regexp-match? #px"^\\s*$" " ") ; #t
(regexp-replace* #px"\\s+" "a b c" " ") ; "a b c"
(regexp-replace #rx"(.*), (.*)" "Lovelace, Ada" "\\2 \\1") ; "Ada Lovelace"
(regexp-replace* #px"\\b\\w" "hello big world" string-upcase) ; "Hello Big World"
(regexp-split #rx"," "a,b,,c") ; '("a" "b" "" "c")
(regexp-match #px#"\\x00(.)" #"\0z") ; a byte regexp: '(#"\0z" #"z")
(match "2026-11-13" [(regexp #px"(\\d+)-(\\d+)-(\\d+)" (list _ y m d)) (list y m d)])
regexp pattern of match.Not described
Known, not yet covered
- Reference: the full argument lists of the matching functions (
#:match-select,#:gap-select?and the input-prefix argument), the matching on ports (what is consumed,regexp-match-peek-positions-immediateand the/endvariants), the locale and grapheme-cluster string functions and Unicode data details were not described in full. - Reference:
racket/stringis described from the Reference chapter's headings and signatures; the argument keywords ofstring-split,string-trimandstring-replaceare given from memory. - Viewer: a regular-expression literal is coloured as a string with its escapes, not as regular-expression syntax (groups, classes and quantifiers are not marked).
See also
- Lexical structure –
#rx,#pxand string escapes - Pattern matching –
regexppatterns inmatch - I/O and ports – ports as the input of a match