Skip to content

Filtering by Assembly Code — using a regular expression (regex)

When a rule applies to a structured set of Assembly Codes, maintaining long inclusion lists becomes inefficient and error-prone.

In those cases, a regular expression (regex) is the preferred solution.

(
  /* AssemblyCode regex */
  $assemblyCodeRegex := /^(32\.[13][15])$/i;

  /* Filter FamilySymbols */
  $familySymbols := $[
    type = "FamilySymbol"
    and $match(values.assemblyCode, $assemblyCodeRegex)
  ].id;

  /* Filter FamilyInstances */
  $[
    type = "FamilyInstance"
    and parent.id in $familySymbols
  ].{
    "id": id,
    "type": type,
    "name": name,
    "parent": parent.id
  }
)

What this filter does (plain language)

“Select all placed elements whose family type has an Assembly Code that matches a defined pattern.”

With this regex, the allowed Assembly Codes are:

  • 32.11
  • 32.15
  • 32.31
  • 32.35

Nothing else is included.


Step 1 — define the Assembly Code pattern

$assemblyCodeRegex := /^(32\.[13][15])$/i;

What this regex means

  • ^ → start of string
  • 32\. → literal 32.
  • [13] → either 1 or 3
  • [15] → either 1 or 5
  • $ → end of string
  • i → case-insensitive (included for consistency)

This explicitly matches four valid codes, without listing them individually.


Why use a regex instead of a list

Compared to:

["32.11", "32.15", "32.31", "32.35"]

A regex:

  • Expresses the structure of the codes
  • Scales cleanly when the pattern expands
  • Avoids manual maintenance of long lists
  • Reduces copy-paste errors

This is ideal when Assembly Codes follow a clear convention.


Step 2 — filter FamilySymbols using $match()

$familySymbols := $[
  type = "FamilySymbol"
  and $match(values.assemblyCode, $assemblyCodeRegex)
].id;

Key points:

  • Assembly Code is a type property
  • Regex comparison is done with $match(string, regex)
  • Missing or null values safely evaluate to false This means missing Assembly Codes are excluded from the scope, not reported.
  • No invalid data is hidden or corrected here

This step answers:

“Which family types comply with this Assembly Code pattern?”


Step 3 — select instances of those types

$[
  type = "FamilyInstance"
  and parent.id in $familySymbols
]

This links:

  • Instance → FamilySymbol
  • FamilySymbol → Assembly Code pattern

Each result represents one placed element of a compliant type.


Important differences vs list-based filtering

Inclusion list Regex
Explicit values Pattern-based
Very safe Requires precision
Less flexible Highly flexible
Verbose Compact

Regex increases expressive power — but also responsibility.


Common mistakes to avoid

Forgetting anchors

/32\.[13][15]/

❌ Over-matches unintended values.


Using in with regex

values.assemblyCode in $assemblyCodeRegex

❌ Invalid — regex must be used with $match().


Making the regex too broad

/^32\./

⚠️ Likely to include unintended Assembly Codes.


When not to use regex

Avoid regex when:

  • The allowed values are few and unrelated
  • Rule clarity is more important than compactness
  • Non-technical users must maintain the rule

In those cases, explicit lists are safer.


Key takeaway

Use regex when Assembly Codes follow a clear structure. Use lists when certainty matters more than flexibility.


Why regex is powerful — a real-world example

So far, we used regex to replace short inclusion lists.

Now let’s look at a realistic industry example where a list would be impractical.

/^(13\.2\d|17\.1[123]|17\.2[0135]|21\.2[01235]|22\.2[0123]|23\.2[0-5]|27\.2[0-6]|28\.[13][0-2]|2[1237]\.2|28\.[13])$/i

At first glance, this looks intimidating. In reality, it is just a compact way of describing many allowed Assembly Codes.


What this regex represents

This single expression replaces dozens of explicit values, such as:

  • 13.20, 13.21, 13.22, …
  • 17.11, 17.12, 17.13
  • 17.20, 17.21, 17.23, 17.25
  • 21.20, 21.21, 21.22, 21.23, 21.25
  • 22.20 through 22.23
  • 23.20 through 23.25
  • 27.20 through 27.26
  • 28.10, 28.11, 28.12, 28.30, 28.31, 28.32
  • 21.2, 22.2, 23.2, 27.2
  • 28.1, 28.3

Writing this as a list would be:

  • Long
  • Hard to maintain
  • Easy to get wrong

How to read this regex (conceptually)

You do not need to read this character by character.

Instead, read it like this:

“Match specific structured groups of Assembly Codes, each group following a predictable numeric pattern.”

Each | separates a group:

13.2x
17.1[1–3]
17.2[0,1,3,5]
21.2[0,1,2,3,5]
22.2[0–3]
23.2[0–5]
27.2[0–6]
28.1[0–2]
28.3[0–2]
21.2, 22.2, 23.2, 27.2
28.1, 28.3

Each group encodes:

  • A domain decision
  • Not an arbitrary value list

Why regex is superior here

1. Intent is explicit

A regex says:

“These codes follow a pattern.”

A list says:

“These are the values I remembered to include.”

Patterns are harder to forget.


2. Changes are safer

If tomorrow:

  • 23.26 becomes valid

You change one character:

23\.2[0-6]

Instead of:

  • Searching a long list
  • Adding another value
  • Risking duplicates or omissions

3. Validation stays predictable

Because the regex is:

  • Anchored (^ and $)
  • Explicit per group

You avoid accidental matches like:

  • 213.21
  • 23.200
  • 27.29

Which would easily slip through a poorly written list or loose regex.


Important warning: regex is power tooling

Regex is a scalpel, not a hammer.

Used well:

  • Rules are compact
  • Scope is clear
  • Maintenance cost drops

Used poorly:

  • You over-match
  • You under-match
  • Nobody understands the rule anymore

When regex is the right choice

Use regex when:

  • Codes are structured
  • Rules are derived from standards
  • The allowed set follows logic, not coincidence
  • The rule is reviewed and owned by technical users

Avoid regex when:

  • Values are arbitrary
  • Non-technical users must edit rules
  • The pattern cannot be explained in one sentence

Best practice when using complex regex

  1. Always anchor (^ and $)
  2. Group logically (use | per domain group)
  3. Comment the intent in the rule description
  4. Test with real data before deploying
  5. Prefer clarity over cleverness

If you cannot explain what the regex does in plain language, it does not belong in a production rule.


Final takeaway

Lists enumerate values. Regex expresses structure.

Once users grasp this difference, regex stops being scary — and starts being one of the most valuable tools in rule authoring.


Pro tip — use regex101.com to build and test your regex

When working with regex, never write it blindly inside a DAQS rule.

Use this website instead:

👉 https://regex101.com/


Why regex101 is so useful

regex101 allows you to:

  • Test your regex live against example values
  • See exactly which part matches
  • Catch over-matching and under-matching early
  • Debug complex patterns step by step

This is especially valuable when:

  • Replacing long inclusion lists
  • Encoding standards-based code ranges
  • Working with regex you didn’t write yourself

  1. Copy real Assembly Code values from DAQS Assist output
  2. Paste them into the test string field on regex101
  3. Paste your regex into the regex field
  4. Verify:

  5. All intended values match

  6. No unintended values match
  7. Only then copy the regex into your DAQS rule

Important settings on regex101

  • Regex flavour: ECMAScript / JavaScript
  • Use anchors (^ and $)
  • Keep the i flag only if intentional

JSONata uses JavaScript-style regex, so regex101 is a correct match.


Strong recommendation

If you haven’t tested your regex on regex101, it’s not ready for the Playground — let alone Production.

This habit alone will save you hours of debugging and review cycles.