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.
| Where | Engine | Case | Where it has to match | Notes |
|---|---|---|---|---|
| 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) | JavaScript | Case-insensitive, always | Anywhere in the text | Do 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) | JavaScript | Case-sensitive | Anywhere in the value unless you anchor it | Anchor with ^ and $ to check the whole value. An empty value passes. Write a slash as \/. |
| Hotfolder filename mask (Import from a Hotfolder) | Python | Case-sensitive unless the pattern starts with (?i) | From the start of the file name | Ends only where you say: .*\.pdf$ needs its $. |
| Email attachment mask (Import from Email) | Python | Case-sensitive unless the pattern starts with (?i) | From the start of the file name | The default, (?i).*\.(pdf|tiff?|png|jpe?g|heic)$, shows the shape. |
| Email sender and subject filters (Import from Email) | Python | Case-insensitive, always | Anywhere 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
| Token | Meaning |
|---|---|
^ | the start of the text |
$ | the end of the text |
\b | a word boundary: the edge of a word, so \bnote\b matches note but not notes or footnote |
One character
| Token | Meaning |
|---|---|
. | any single character |
\d | a digit, 0 to 9 |
\w | a letter, digit or underscore |
\s | a 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
| Token | Meaning |
|---|---|
? | 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
| Token | Meaning |
|---|---|
(...) | treat what is inside as one thing |
a|b | either 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
\.;.pdfalso matchesxpdf. - 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.
| Pattern | Matches | What it says |
|---|---|---|
\bcredit\s*note\b | CREDIT NOTE | the words credit note, with any spacing between them, and not inside a longer word |
^CS_ | CS_1_31491673.pdf | a file name starting with CS_ |
\.(png|jpe?g)$ | scan.JPG | a file name ending in .png, .jpg or .jpeg |
invoice\s*(no|number|#) | Invoice No: 506372 | an invoice number label in any of its usual spellings |
(tax|vat)\s+invoice | FINAL DA / TAX INVOICE | tax invoice or VAT invoice, with any spacing |
\d{2}[./-]\d{2}[./-]\d{4} | 07-09-2026 | a date with dots, slashes or hyphens between the parts |
\bIBAN\b.{0,5}[A-Z]{2}\d{2} | IBAN: GB29 | the 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".
| Pattern | Matches | What it says |
|---|---|---|
^\d{4}$ | 2026 | exactly four digits, and nothing else |
^GB\d{9}$ | GB123456789 | GB followed by nine digits |
^[A-Z]{2}\d{6}$ | AB123456 | two capital letters, then six digits |
^INV-\d+$ | INV-4021 | INV- followed by at least one digit |
^\d{2}\/\d{2}\/\d{4}$ | 31/12/2026 | a date with slashes, each one escaped |
^[A-Za-z0-9 -]+$ | Acme Ltd - 4 | letters, digits, spaces and hyphens only |
^(EUR|USD|GBP)$ | EUR | one 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.
*.pdfis 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
.*\.pdfalso acceptsreport.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.
notealso matches footnote and notes. Put\bon 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.