LessonsAdvanced: Bigger programsLesson 38

Regular expressions

Describe patterns of text, then find them, pull out their parts and replace them, with matchText, matchChunk, replaceText and filter.

  • Advanced
  • Lesson 38 of 83
  • About 11 minutes
  • 8 examples

Patterns for text

A regular expression (a regex) is a small language for describing text: "one or more digits", "a word at the start of the line", "something that looks like an email address". xTalk uses the same regular expressions as Perl, Python and most other languages (PCRE), so what you learn here works almost everywhere.

PatternMatches
catthe letters cat, anywhere
.any one character
[aeiou], [0-9], [^,]one character from a set, a range, or not in a set
\d, \s, \wa digit, a space or tab, a letter or digit or _
*, +, ?after something: any number of it, one or more, none or one
{3}, {2,4}exactly 3 of it, from 2 to 4
^, $the start and the end of the text
(...)a group, which you can capture
a|beither a or b
\., \$a character that means something, taken literally

Is it there? matchText

matchText says whether a pattern is found anywhere in some text:

ExampleRun it in the playground
put matchText("Order 66 shipped", "[0-9]+")
put matchText("No numbers here", "[0-9]+")
put matchText("2024", "^\d{4}$")
put matchText("12024", "^\d{4}$")
Output
true
false
true
false

The last two show why ^ and $ matter: without them, "four digits" would be found inside a longer number.

Taking parts out: groups

Give matchText variables after the pattern, and each bracketed group's text is put into one of them, in order. This is how you pull a date, a price or a name out of a line:

ExampleRun it in the playground
put "Order 66 shipped on 2024-05-01" into tLine
if matchText(tLine, "(\d{4})-(\d{2})-(\d{2})", tYear, tMonth, tDay) then
   put "Year" && tYear & ", month" && tMonth & ", day" && tDay
end if
get matchText("Ada Lovelace", "(\w+)\s+(\w+)", tFirst, tLast)
put tLast & "," && tFirst
Output
Year 2024, month 05, day 01
Lovelace, Ada

Where is it? matchChunk

matchChunk is the same, but gives the positions of each group, the first and last character, so you can work on that chunk of the text. Here it finds every price in a line and adds them up:

ExampleRun it in the playground
put "price: $12.50, tax: $1.25, tip: $2" into tRest
put 0 into tTotal
repeat while matchChunk(tRest, "\$([0-9.]+)", tStart, tEnd)
   add char tStart to tEnd of tRest to tTotal
   delete char 1 to tEnd of tRest
end repeat
put tTotal
Output
15.75

Replacing: replaceText

replaceText gives a copy of the text with every match of the pattern replaced. It is replace with patterns:

ExampleRun it in the playground
put replaceText("too   many    spaces", " +", " ")
put replaceText("Call 555-1234 or 555-9876", "\d{3}-\d{4}", "XXX-XXXX")
put replaceText("one,two;three four", "[,; ]", "|")
Output
too many spaces
Call XXX-XXXX or XXX-XXXX
one|two|three|four

Ignoring case

Regular expressions care about capitals. Start the pattern with (?i) to make it ignore case:

ExampleRun it in the playground
put matchText("Hello", "^hello$")
put matchText("Hello", "(?i)^hello$")
Output
false
true

Checking input

A common use is checking that what someone typed has the right shape:

ExampleRun it in the playground
function looksLikeEmail pText
   return matchText(pText, "^[^@\s]+@[^@\s]+\.[a-zA-Z]{2,}$")
end looksLikeEmail

function looksLikePostcode pText
   return matchText(pText, "(?i)^[A-Z]{1,2}\d[A-Z\d]?\s*\d[A-Z]{2}$")
end looksLikePostcode

put looksLikeEmail("ada@example.com")
put looksLikeEmail("not an email")
put looksLikePostcode("SW1A 1AA")
put looksLikePostcode("12345")
Output
true
false
true
false
A mistakeIt stops with an error on line 1
put matchText("abc", "[a-z")

Try it yourself

From the log line 2026-11-05 21:30:07 ERROR disk full on /dev/sda1, pull out the time, the level and the message, and put them as [ERROR at 21:30:07] disk full on /dev/sda1.

Show a solution
ExampleRun it in the playground
put "2026-11-05 21:30:07 ERROR disk full on /dev/sda1" into tLine
if matchText(tLine, "^\S+ (\S+) (\w+) (.*)$", tTime, tLevel, tMessage) then
   put "[" & tLevel && "at" && tTime & "]" && tMessage
end if
Output
[ERROR at 21:30:07] disk full on /dev/sda1

Words in this lesson

Each one finds every lesson that uses it. The Dictionary has the whole story of each, with its syntax and more examples.