Hi,
please check my posts how to start with Parsers:
it explains how to take the texts blob and make it parsable.
Regarding parser structure, there is your exact example described in part 2
I hope it helps.
In your case, you actually have two pattern.
The first one is when subline 12 not present:
stats_pattern1 =
```
line one {main:string}
sub-line3 {value1:string} is target and sub-line3 will always be there
sub-line8 {value2:string} is target and sub-line8 will always be there
sub-sub-line9 {value3:string} is target and sub-sub-line9 will always be there
```;
The second one of subline 12 is present:
stats_pattern2 =
```
line one {main:string}
sub-line3 {value1:string} is target and sub-line3 will always be there
sub-line8 {value2:string} is target and sub-line8 will always be there
sub-sub-line9 {value3:string} is target and sub-sub-line9 will always be there
sub-line12 {value4:string} is target and may or may not be present
sub-sub-line13 {value5:string} is target and sub-sub-line13 will be there if sub-line12 is present
```;
The reason you need two pattern is that in your select statement you are asking for the output of value 4 and value 5 that do not exist in stats_pattern1:
select {
main: r.data.main,
value1: r.data.value1,
value2: r.data.value2,
value3: r.data.value3,
value4: r.data.value4,
value5: r.data.value5
}
additionally you have to replace:
let my_data = blockMatches(parsed_resonse, pattern)
with
foreach r in blockMatches(parsed_respone, stats_pattern)
to allow NQE to iterate over each line of block code.
Here is your NQE with both patterns that matches subline 12 pattern:
stats_pattern1 =
```
line one {main:string}
sub-line3 {value1:string} is target and sub-line3 will always be there
sub-line8 {value2:string} is target and sub-line8 will always be there
sub-sub-line9 {value3:string} is target and sub-sub-line9 will always be there
```;
stats_pattern2 =
```
line one {main:string}
sub-line3 {value1:string} is target and sub-line3 will always be there
sub-line8 {value2:string} is target and sub-line8 will always be there
sub-sub-line9 {value3:string} is target and sub-sub-line9 will always be there
sub-line12 {value4:string} is target and may or may not be present
sub-sub-line13 {value5:string} is target and sub-sub-line13 will be there if sub-line12 is present
```;
foreach device in network.devices
foreach command in device.outputs.commands
where command.commandText == "show my lines"
let parsed_respone = parseConfigBlocks(OS.UNKNOWN, command.response)
foreach r in blockMatches(parsed_respone, stats_pattern2)
select {
main: r.data.main,
value1: r.data.value1,
value2: r.data.value2,
value3: r.data.value3,
value4: r.data.value4,
value5: r.data.value5
}
Thank you. I’ll study this today and follow-up with “Best answer”
I apologize for the delayed response; I haven’t have time to get this to work with both patterns. Pattern2 runs fine when there is a match but if not if value 4 and value 5 are missing, i.e. matches pattern1. I hope to have some time this week to research the solution for myself. Thank you.
Hi @dakotaglory ,
try this one. It addresses the missing value 4 and 5
stats_pattern =
```
line one {main:string}
sub-line3 {value1:string} is target and sub-line3 will always be there
sub-line8 {value2:string} is target and sub-line8 will always be there
sub-sub-line9 {value3:string} is target and sub-sub-line9 will always be there
```;
stats_pattern2 =
```
line one {main:string}
sub-line3 {value1:string} is target and sub-line3 will always be there
sub-line8 {value2:string} is target and sub-line8 will always be there
sub-sub-line9 {value3:string} is target and sub-sub-line9 will always be there
sub-line12 {value4:string} is target and may or may not be present
sub-sub-line13 {value5:string} is target and sub-sub-line13 will be there if sub-line12 is present
```;
foreach device in network.devices
foreach command in device.outputs.commands
where command.commandText == "show my lines"
let parsed_respone = parseConfigBlocks(OS.UNKNOWN, command.response)
foreach r in blockMatches(parsed_respone, stats_pattern)
let rPlus = max(foreach match in blockMatches(parsed_respone, stats_pattern2)
where match.data.main == r.data.main
select match)
select {
main: r.data.main,
value1: r.data.value1,
value2: r.data.value2,
value3: r.data.value3,
value4: rPlus?.data?.value4,
value5: rPlus?.data?.value5
}
credits for this enhancement is to @Tyson Henrie
Thank you Tyson
can you post the entirety of the NQE with the enhancement in 1 code block?
Hi @CarlB
Can you use the code block above?
having to modify to match my environment and hitting the usual challenges. Is that final block 100% with all replacements/modifications?
@CarlB That example is fairly generic. If you are having trouble adapting that to your use case. Can you share a sanitized example of the data file you are trying to parse and the query you are currently using? That might be good as a new post.
I think I have it working.
NHRPnoFWpattern =
```
{IPandPrefix:string} via {VPNpeer: ipv4Address}
{tunnelnum: string} created
NBMA address: {TunPublic: ipv4Address}
```;
NHRPwithNATpattern =
```
{IPandPrefix:string} via {VPNpeer: ipv4Address}
{tunnelnum: string} created
NBMA address: {TunPublic: ipv4Address}
{string} NBMA address: {NoNATtunPublic: string}
```;
cleanParen(s) = cleanLParen(cleanRParen(s));
cleanLParen(s) = replaceMatches(s, "(", "");
cleanRParen(s) = replaceMatches(s, ")", "");
foreach device in network.devices
foreach command in device.outputs.commands
where command.commandType == CommandType.NHRP_STATE
foreach x in <1]
//let ParsedResponse = parseConfigBlocks(OS.UNKNOWN, command.response)
let ParsedResponse = parseConfigBlocks(OS.UNKNOWN, cleanParen(command.response))
foreach r in blockMatches(ParsedResponse, NHRPnoFWpattern)
let rPlus = max(foreach match in blockMatches(ParsedResponse, NHRPwithNATpattern)
where match.data.IPandPrefix == r.data.IPandPrefix
select match)
select {
Prefix: r.data.IPandPrefix,
IP: r.data.VPNpeer,
ARIN: r.data.TunPublic,
LAN: rPlus?.data?.NoNATtunPublic
}
@CarlB going to use the code embedding so its easier for others to read. Thanks for posting!!
NHRPnoFWpattern =
```
{IPandPrefix:string} via {VPNpeer: ipv4Address}
{tunnelnum: string} created
NBMA address: {TunPublic: ipv4Address}
```;
NHRPwithNATpattern =
```
{IPandPrefix:string} via {VPNpeer: ipv4Address}
{tunnelnum: string} created
NBMA address: {TunPublic: ipv4Address}
{string} NBMA address: {NoNATtunPublic: string}
```;
cleanParen(s) = cleanLParen(cleanRParen(s));
cleanLParen(s) = replaceMatches(s, "(", "");
cleanRParen(s) = replaceMatches(s, ")", "");
foreach device in network.devices
foreach command in device.outputs.commands
where command.commandType == CommandType.NHRP_STATE
foreach x in 1]
//let ParsedResponse = parseConfigBlocks(OS.UNKNOWN, command.response)
let ParsedResponse = parseConfigBlocks(OS.UNKNOWN, cleanParen(command.response))
foreach r in blockMatches(ParsedResponse, NHRPnoFWpattern)
let rPlus = max(foreach match in blockMatches(ParsedResponse, NHRPwithNATpattern)
where match.data.IPandPrefix == r.data.IPandPrefix
select match)
select {
Prefix: r.data.IPandPrefix,
IP: r.data.VPNpeer,
ARIN: r.data.TunPublic,
LAN: rPlus?.data?.NoNATtunPublic
}