Skip to content

Regex patterns

Regular expressions cover what exact lines and wildcards cannot: alternatives, number ranges, “only these and nothing else”. rConfig uses PHP (PCRE) regular expressions in four places, and they do not all treat flags and case the same way. This page shows each, with results asserted by the rConfig Pro test suite.

WhereApplied toCase by default
must_match_regex, must_not_match_regexThe whole config as one block of textSensitive
re: line in a code block methodOne config line at a timeInsensitive, unless delimited without i
regex: item in evaluate_blockThe whole config, or the whole section when scopedSensitive

Write the pattern with delimiters and flags, PHP style: /pattern/flags. Because the pattern runs against the whole config at once:

  • Without the m flag, ^ and $ mean the start and end of the whole config, not of a line.
  • Without the s flag, . does not cross line breaks.
  • A JavaScript-style g flag is accepted and has no effect on the result.

A pattern written without delimiters is wrapped in /.../ for you, with no flags. A pattern with an opening delimiter but no closing one never matches, so the rule fails rather than raising an error.

// Case-insensitive
#[must_match_regex]
/ip address/i
// Case-sensitive
#[must_match_regex]
/ip address/
// Start of a line
#[must_match_regex]
/^IP address/m
// Whole word
#[must_match_regex]
/\bTime\b/
// Partial word with boundaries
#[must_match_regex]
/\bTim\b/
// Alternation, any line
#[must_match_regex]
/^(?:IP|MAC) address: .+$/im
// Not present
#[must_match_regex]
/password: \w+/

Against this text:

IP address: 192.0.2.1
MAC address: 00:00:5E:00:53:01
Time: 14:30:45
Username: admin@example.com
RuleResult
/ip address/ipass
/ip address/fail
/^IP address/mpass
/\bTime\b/pass
/\bTim\b/fail
/^(?:IP|MAC) address: .+$/impass
/password: \w+/fail

Source: PolicyMethodsTest::test_must_match_regex_with_various_patterns. Minimum version 8.0.0.

// RSTP edge ports are configured
#[must_match_regex]
/^set protocols rstp interface (ge|xe|et)-\d+\/\d+\/\d+\.\d+ edge$/gm
// RSTP edge ports are disabled
#[must_match_regex]
/^set protocols rstp interface (ge|xe|et)-\d+\/\d+\/\d+\.\d+ disabled$/gm
set protocols rstp interface ge-0/0/1.0 edge
set protocols rstp interface ge-0/0/2.0 edge
set protocols rstp interface ge-0/0/3.0 edge
set protocols rstp interface xe-0/0/3.0 edge
set protocols rstp interface xe-0/0/2.0 edge
set protocols rstp interface xe-0/0/1.0 edge
set protocols ospf area 0.0.0.0 interface ge-0/0/1.0
set protocols rstp interface xe-0/0/2.0 edge
some other configuration line
set system services ssh
set protocols rstp interface et-0/0/3.0 edge
another non-matching line
set protocols bgp group EXTERNAL-PEERS type external
set protocols rstp interface et-0/0/4.10 edge
set protocols rstp interface et-0/0/1.0 edge
set protocols rstp interface et-0/0/2.0 edge
set protocols rstp interface et-0/0/3.0 edge
RuleResult
Edge ports configuredpass
Edge ports disabledfail

Source: PolicyMethodsTest::test_must_match_regex_with_gm_flags. The / characters inside the pattern are escaped as \/ because / is the delimiter.


The inverse of must_match_regex: the rule passes when the pattern is not found. The same delimiter and flag rules apply.

// bridge1 does not have fast-forward enabled
#[must_not_match_regex]
/add name=bridge1 fast-forward=yes/m
/interface bridge
add name=bridge1 fast-forward=yes
add name=bridge2 fast-forward=no
/interface ethernet
set [find default-name=ether1] name=ether1-gateway
set [find default-name=ether2] name=ether2-local
/ip dhcp-client
add disabled=no interface=ether1-gateway

Result: fail, because the forbidden line is present. Source: PolicyMethodsTest::test_must_not_match_regex_pattern_found. Minimum version 8.0.2.


Lookaheads let one pattern say “these must exist, and nothing else may”. The approved local accounts rule on the IOS-XE pages uses this technique, and its caution explains the one case it misses.


In match_code_block_from_array, match_code_block_strict and match_code_block_flexible, a body line starting with re: is a regular expression tested against one config line at a time.

  • re:pattern without delimiters is case-insensitive.
  • re:/pattern/flags uses exactly the flags you give. Leave out i and it is case-sensitive.
// Loopback0 description follows the naming standard
#[match_code_block_from_array]
re:^interface Loopback0$
re:^\s*description LOOP:null:Loopback0:[a-z]{3}[0-9]{2}\.[a-z]{4}[0-9]{2}-[a-z]{2}:null:\[\]$
interface Loopback0
description LOOP:null:Loopback0:lab01.site01-ar:null:[]
interface GigabitEthernet1
description Uplink

Result: pass. Source: PolicyMethodsTest::test_match_code_block_from_array_raw_regex_match and CustomerUseCases/MatchCodeBlockRawRegexCustomerTest.

With delimiters, case matters:

// Loopback0 description, case-sensitive
#[match_code_block_from_array]
re:/^interface Loopback0$/m
re:/^\s*description LOOP:null:Loopback0:[a-z]{3}[0-9]{2}\.[a-z]{4}[0-9]{2}-[a-z]{2}:null:\[\]$/m
// Loopback0 description, case-insensitive
#[match_code_block_from_array]
re:/^interface Loopback0$/mi
re:/^\s*description LOOP:null:Loopback0:[a-z]{3}[0-9]{2}\.[a-z]{4}[0-9]{2}-[a-z]{2}:null:\[\]$/mi
interface Loopback0
description LOOP:null:Loopback0:LAB01.SITE01-AR:null:[]
RuleResult
Case-sensitive (/m)fail
Case-insensitive (/mi)pass

Source: PolicyMethodsTest::test_match_code_block_from_array_raw_regex_case_sensitive_negative and test_match_code_block_from_array_delimited_regex_honors_flags. Minimum version 8.0.0.


In an evaluate_block rule, a regex: item works like must_match_regex: it is tested against the whole config, or the whole section when the rule has a scope:. Quote the pattern in YAML.

// NTP configured, a known syslog host, and no telnet
#[evaluate_block]
all:
- regex: "^ntp server "
- any:
- logging host 192.0.2.1
- logging host 192.0.2.2
- not: transport input telnet
ntp server 192.0.2.1
logging host 192.0.2.2

Result: pass. Source: Engine/PolicyExpressionEngineTest::test_whole_file_boolean_without_scope. Minimum version 8.3.0.