blockMatches
blockMatches(config: List<ConfigLine>, pattern: PatternBlocks<T>) : Bag<{data: T, blocks: MatchBlocks, diffCount: Integer}>
Matches the block pattern pattern against the config lines in config and their children, and returns one record for
each way that the pattern matches. If the pattern does not match, the result is an empty bag.
Each record has the following fields:
data: TThe data extracted by all lines of the pattern, merged into one record.blocks: MatchBlocksThe config lines that the pattern lines matched, with their hierarchy.diffCount: IntegerAlways0, becauseblockMatchesreturns only complete matches. See blockDiff for partial matches.
The result is a Bag, so the records have no defined order. The result contains at most 1,000,000 records. Matches
beyond that limit are dropped without an error.
See Block Patterns for the block pattern syntax, and Details on Patterns for the syntax of each pattern line.
Matching rules
- Each top-level pattern line must match a line in
config. Each indented pattern line must match a child of the config line that its parent pattern line matched. - Pattern lines at the same level must each match a different config line. In other words, distinct pattern occurrences at a level match distinct config lines.
- The order of the config lines does not need to match the order of the pattern lines.
- Each pattern line is matched against a config line with the same rules as
patternMatch. See patternMatch matching rules. To require each pattern line to match the whole config line, end the pattern line with{eof}or use withOption withLineMatchingOption.COMPLETE. - Unmatched config lines (that is, config lines that are not matched by any pattern line) are allowed. To forbid them,
add a
{%unmatched-config:forbid%}line to the pattern. It applies to the level where it appears and to all deeper levels. It does not apply to the children of a config line matched by a pattern line that has no indented lines of its own. - A pattern line that starts with
{%-%}is negated: the match fails if any config line at that level matches it. - The
datarecord contains the named components of all pattern lines. Using the same name in two pattern lines is a type-checking error.
Null inputs
If config, any item in config, or pattern is null, the query fails with the error
First argument to “blockMatches” was null; consider adding an isPresent() condition. (or Second argument for
pattern). The config field of a device's files is nullable. Use
isPresent to exclude null values before calling blockMatches.
Examples
Each example matches a pattern against the following configuration:
hostname r1
interface GigabitEthernet1
description uplink
ip address 10.0.0.1 255.255.255.0
ip address 10.0.1.1 255.255.255.0 secondary
interface GigabitEthernet2
ip address 10.0.2.1 255.255.255.0
shutdown
interface GigabitEthernet3
shutdown
router bgp 65000
neighbor 10.0.0.2 remote-as 65001
You can try out each of these examples in NQE by inserting the pattern into the pattern variable in the following
template:
text =
"""
hostname r1
interface GigabitEthernet1
description uplink
ip address 10.0.0.1 255.255.255.0
ip address 10.0.1.1 255.255.255.0 secondary
interface GigabitEthernet2
ip address 10.0.2.1 255.255.255.0
shutdown
interface GigabitEthernet3
shutdown
router bgp 65000
neighbor 10.0.0.2 remote-as 65001
""";
pattern = ```
<your pattern here>
```;
foreach match in blockMatches(parseConfigBlocks(OS.IOS, text), pattern)
select { data: match.data, blocks: match.blocks }
Single-line pattern
With pattern
interface {name:string}
We get results
data |
blocks |
|---|---|
{name: "GigabitEthernet1"} |
|
{name: "GigabitEthernet2"} |
|
{name: "GigabitEthernet3"} |
|
Each matching config block produces one record. The blocks field contains only the config lines that pattern lines
matched, not the children of those lines.
Nested pattern lines
With pattern
interface {name:string}
shutdown
We get results
data |
blocks |
|---|---|
{name: "GigabitEthernet2"} |
|
{name: "GigabitEthernet3"} |
|
The indented pattern line shutdown must match a child of the matched interface line. GigabitEthernet1 has no
shutdown child, so it does not match.
Several matches in one block
With pattern
interface {name:string}
ip address {ip:ipv4Address}
We get results
data |
blocks |
|---|---|
{name: "GigabitEthernet1", ip: 10.0.0.1} |
|
{name: "GigabitEthernet1", ip: 10.0.1.1} |
|
{name: "GigabitEthernet2", ip: 10.0.2.1} |
|
The result contains one record for each way that the pattern matches. GigabitEthernet1 has two ip address lines, so
it produces two records. Each pattern line needs to match only the start of a config line, so the text after the
address, such as 255.255.255.0 secondary, is ignored.
Pattern lines in a different order
With pattern
interface {name:string}
shutdown
ip address {ip:ipv4Address}
We get results
data |
blocks |
|---|---|
{name: "GigabitEthernet2", ip: 10.0.2.1} |
|
In the configuration, ip address comes before shutdown. The pattern lists them in the opposite order and still
matches.
Negated pattern line
With pattern
interface {name:string}
{%-%} shutdown
We get results
data |
blocks |
|---|---|
{name: "GigabitEthernet1"} |
|
The {%-%} prefix negates the shutdown line. An interface block matches only if none of its children match
shutdown, so GigabitEthernet2 and GigabitEthernet3 do not match.
Forbidding unmatched config lines
With pattern
interface {name:string}
shutdown
{%unmatched-config:forbid%}
We get results
data |
blocks |
|---|---|
{name: "GigabitEthernet3"} |
|
{%unmatched-config:forbid%} requires every child of the matched interface line to match a pattern line.
GigabitEthernet2 also has an ip address child that no pattern line matches, so it does not match.
Several top-level pattern lines
With pattern
interface {name:string}
shutdown
router bgp {asn:number}
We get results
data |
blocks |
|---|---|
{name: "GigabitEthernet2", asn: 65000} |
|
{name: "GigabitEthernet3", asn: 65000} |
|
Each top-level pattern line matches a different top-level config block. The result contains one record for each
combination of matching blocks, and the data record merges the components of both blocks.
No match
With pattern
router ospf {id:number}
We get no records. The configuration has no line that starts with router ospf, so the result is an empty bag.
Example query
The following query lists the interfaces that are not shut down on each device, along with the matched config lines.
pattern = ```
interface {name:string}
{%-%} shutdown
```;
foreach device in network.devices
where isPresent(device.files.config)
foreach match in blockMatches(device.files.config, pattern)
select {device: device.name, interface: match.data.name, blocks: match.blocks}
blockMatches returns a bag, so the query uses a foreach qualifier to iterate over the matches. The
where isPresent(device.files.config) condition skips devices that have no config.
blockMatches also accepts a Bag<ConfigLine> as its first argument. A Bag has no defined order, so this overload
produces a warning. Use orderBy() or order() to convert the argument to a List<ConfigLine>. In a future release,
the warning will become a type-checking error.
See also
Guides
Types
Functions
- hasBlockMatch: Checks whether
blockMatchesreturns at least one match. UsehasBlockMatchinstead ofblockMatcheswhen you only need to know whether the pattern matches.hasBlockMatchstops after it finds one match, so it does less work. - blockDiff: Gets the closest partial match of a block pattern, including the pattern lines that are missing and the config lines that are extraneous.
- blockPattern: Creates a block pattern from a string.
- withOption: Changes how a block pattern handles unmatched config lines and partial line matches.
- patternMatches: Matches a single-line pattern against each line in a list of config lines.