Skip to main content

Regular Expressions

A regular expression (a regex or pattern) describes a shape of text: "GB followed by nine digits", "the words credit note with any spacing between them", "a file name that ends in .pdf". Several places in DocAI Fabric take one, and each applies it slightly differently. This page covers what a pattern is, the handful of characters worth knowing, worked examples, and the table of where patterns are used and how each place runs them.

If you would rather not write one, every pattern box that has the assistant switched on carries a Build with AI button: describe what you want in plain words and it writes the pattern, already shaped for the place you are in.

Where patterns are used​

The same pattern can behave differently from one place to the next, and the differences are exactly where mistakes happen. Check the row for the place you are in before you write anything.

WhereEngineCaseWhere it has to matchNotes
Classification rules, a condition with the Regex match type on the source file name, the document text, a metadata value or a field value (Classify)JavaScriptCase-insensitive, alwaysAnywhere in the textDo not write (?i); it is already case-insensitive, and JavaScript rejects the flag. A pattern that does not compile fails the Classify step for every document.
Format Validation by Regex, a business-rule preset on one field (Business Rules)JavaScriptCase-sensitiveAnywhere in the value unless you anchor itAnchor with ^ and $ to check the whole value. An empty value passes. Write a slash as \/.
Hotfolder filename mask (Import from a Hotfolder)PythonCase-sensitive unless the pattern starts with (?i)From the start of the file nameEnds only where you say: .*\.pdf$ needs its $.
Email attachment mask (Import from Email)PythonCase-sensitive unless the pattern starts with (?i)From the start of the file nameThe default, (?i).*\.(pdf|tiff?|png|jpe?g|heic)$, shows the shape.
Email sender and subject filters (Import from Email)PythonCase-insensitive, alwaysAnywhere in the address or subject@vendor\.com$ accepts every address at that domain.

The two engines agree on everything on this page. They part ways on the inline flag (?i): Python reads it as "ignore case", JavaScript reports Invalid group and refuses the whole pattern. Where the table says a place is already case-insensitive, leave the flag out.

Reading a pattern​

Most characters in a pattern stand for themselves: invoice matches the word invoice. A few characters have a meaning of their own.

Where it matches

TokenMeaning
^the start of the text
$the end of the text
\ba word boundary: the edge of a word, so \bnote\b matches note but not notes or footnote

One character

TokenMeaning
.any single character
\da digit, 0 to 9
\wa letter, digit or underscore
\sa space, tab or line break
[A-Z]any one character in the set: A to Z
[^0-9]any one character not in the set
\.a full stop. A backslash makes a special character literal, so \. \( \$ \+ mean the character itself

How many

TokenMeaning
?the thing before it is optional
*none or any number of them
+one or more of them
{3}exactly three of them
{2,4}between two and four of them

Grouping

TokenMeaning
(...)treat what is inside as one thing
a|beither the left side or the right side

That is enough to read almost every pattern you will meet. Two habits keep them honest:

  • Escape what you mean literally. A full stop that should be a full stop is \.; .pdf also matches xpdf.
  • Anchor only when you mean it. ^ and $ say "and nothing before or after". Right for a whole-value format check, wrong for finding a phrase somewhere in a page of OCR text.

Examples: finding text in a document​

These suit a classification condition, a sender filter, or anything else that searches a text. They are unanchored, they mark word edges with \b, and they leave room for the spacing OCR produces.

PatternMatchesWhat it says
\bcredit\s*note\bCREDIT NOTEthe words credit note, with any spacing between them, and not inside a longer word
^CS_CS_1_31491673.pdfa file name starting with CS_
\.(png|jpe?g)$scan.JPGa file name ending in .png, .jpg or .jpeg
invoice\s*(no|number|#)Invoice No: 506372an invoice number label in any of its usual spellings
(tax|vat)\s+invoiceFINAL DA / TAX INVOICEtax invoice or VAT invoice, with any spacing
\d{2}[./-]\d{2}[./-]\d{4}07-09-2026a date with dots, slashes or hyphens between the parts
\bIBAN\b.{0,5}[A-Z]{2}\d{2}IBAN: GB29the word IBAN followed within a few characters by the start of an IBAN

In a classification condition, case never matters, so credit finds CREDIT as well. In a hotfolder or attachment mask it does, unless the pattern starts with (?i).

Examples: checking a whole value​

These suit Format Validation by Regex. They are anchored, because the question is "is this value exactly this shape".

PatternMatchesWhat it says
^\d{4}$2026exactly four digits, and nothing else
^GB\d{9}$GB123456789GB followed by nine digits
^[A-Z]{2}\d{6}$AB123456two capital letters, then six digits
^INV-\d+$INV-4021INV- followed by at least one digit
^\d{2}\/\d{2}\/\d{4}$31/12/2026a date with slashes, each one escaped
^[A-Za-z0-9 -]+$Acme Ltd - 4letters, digits, spaces and hyphens only
^(EUR|USD|GBP)$EURone of exactly these three

Format Validation is case-sensitive: to accept either case in one place, write the set out, as in ^[Gg][Bb]\d{9}$.

Mistakes worth knowing by name​

  • (?i) in a JavaScript place. Classification conditions and Format Validation run on JavaScript, which does not have inline flags. The pattern box tells you it does not compile; fix it before you save, because a classification rule that does not compile fails the Classify step for every document in the transaction, and the Activity Log names the rule and the error.
  • A glob where a regex was expected. *.pdf is not a pattern; .*\.pdf$ is. * on its own repeats nothing.
  • Forgetting the end anchor on a mask. A hotfolder mask matches from the start of the file name and stops wherever the pattern stops, so .*\.pdf also accepts report.pdf.tmp. Add $.
  • A slash in a Format Validation pattern. Write it \/, or the generated rule does not parse. Classification conditions escape it for you; either form works there.
  • Matching inside a word. note also matches footnote and notes. Put \b on the sides that should be word edges.
  • Anchoring a search. ^credit note$ in a classification condition only matches a page whose entire text is those two words. Leave the anchors off.

Testing a pattern​

  • Classification rules. Run a transaction in the Playground and open its Activity Log: each document has a classified as row saying whether the pre-rule matched, whether the LLM was called, and what the post-rule did. A rule that did not compile shows as a failed step with the error text.
  • Format Validation. Open a transaction in the viewer; the field carries the rule's error when the value does not match.
  • Connector masks. Use the connector's Test (dry run), which lists what the mask would pick up without importing anything.
  • Outside the product, any online JavaScript regex tester behaves like the classification and validation places; a Python one behaves like the connector masks.