The Exscript any_match() function uses regex to match patterns in strings and returns the results in a tuple.
I am attempting to match IP addresses in a traceroute output. It works for the most part, but for some reason returns some extra values (in addition to the targeted addresses). I would like some assistance in the correct regex to use that will return only the IP addresses without the extra values.
**Note:**I have googled and searched stackoverflow for regex patterns as well as studied the regex help page. This is the closest regex that's worked so far.
def ios_commands(job, host, conn):
conn.execute('terminal length 0')
conn.execute('tr {}'.format(DesAddr))
print('The results of the traceroute', repr(conn.response))
for hops in any_match(conn,r'(([0-9]{1,3}\.){3}[0-9]{1,3})'):
hop_addresses = list(hops)
OUTPUT
the string being searched
hostname>('The results of the traceroute', "'tr 192.33.12.4\\r\\nType escape sequence to abort.\\r\\nTracing the route to hostname (192.33.12.4)\\r\\nVRF info: (vrf in name/id, vrf out name/id)\\r\\n 1 hostname (192.32.0.174) 0 msec 0 msec 0 msec\\r\\n 2 hostname (192.32.0.190) 0 msec 0 msec 0 msec\\r\\n 3 192.33.226.225 [MPLS: Label 55 Exp 0] 0 msec 4 msec 0 msec\\r\\n 4 192.33.226.237 0 msec 0 msec 0 msec\\r\\n 5 hostname (192.33.12.4) 4 msec * 0 msec\\r\\nhostname>'")
['192.33.12.4', '12.'] #note the extra '12.' value
['192.33.12.4', '12.']
['192.32.0.174', '0.']
['192.32.0.190', '0.']
['192.33.226.225', '226.']
['192.33.226.237', '226.']
['192.33.12.4', '12.']
You have 2 matching groups in your pattern. The first one (and outer one) is for the whole IP address; and the second group is repeated thrice:
([0-9]{1,3}\.){3}
Use non-capturing groups:
((?:[0-9]{1,3}\.){3}[0-9]{1,3})
Related
In TCL, in output I have something like this:
ABBAA 1 BAABA 1 DNS3 0 0 200 300 400 500 0 0
ABBAA 1 BAABA 1 DNS1 0 0 200 300 400 500 0 0
ABBAA 1 BAABA 1 DNS7 0 0 200 300 400 500 0 0
ABBAB 1 BAABB 1 DNS5 0 0 200 300 400 500 0 0
ABBAB 1 BAABB 1 DNS3 0 0 200 300 400 500 0 0
I would like to sort this table alike dataset by fourth column ascending (so the first one will be row with DNS1UP1, then DNS2UP2 etc.) I figured out that regexp will be easiest method by looking for string with "DNS.." in it. But my method doesn't work exacly how I thought, because it is matching only one line or no line at all.
My method:
regexp "ABB.*DNS1.*?\N"
ABB - match beginning of new line
.* - every character between ABB and DNS..
DNS1 - match the main looking for word
.* - every character between DNS... and new line symbol
?\n - non-greedy occurence of new line
Where am I wrong?
If you have a list of lines in such a regular format, you can just lsort them… with the right options. In particular, -dictionary is good for mixed text/numbers and -index 4 lets you choose the column to sort by.
set sortedLines [lsort -index 4 -dictionary $unsortedLines]
The only possible reasonable use of regexp in this would have been in preparing the data for the sort, but that string which you provided is already sortable (assuming you've done a split $data "\n" on it to actually convert it into a list of lines and are not just using a big ol' string).
VB2010 Using regex I cant seem to get this seemingly easy regex to work. I first look for a line with a keyword TRIPS that has my data and then from that line I want to extract repeated groups of data made up of an alpha code and then a number.
MODES 1 0 0
OVERH X 28 H 0 Z 198
TRIPS X 23 D 1 Z 198
ITEMSQ 1 0 0
COSTU P 16 E 180
CALLS 0 0
I have
^TRIPS (?<grp>[A-Z]\s{1,4}\d{1,3})
Which gives me one match and the first group "X 23". So I extend it by allowing it to match up to 4 groups.
^TRIPS (?<grp>[A-Z]\s{1,4}\d{1,3}){0,4}
but I get one match with still only one group.
You aren't allowing for white space between the groups. You need to do something like this:
^TRIPS ((?<grp>[A-Z]\s{1,4}\d{1,3})\s+){0,4}
We have this regex:\\*.*?(.600[0-9]).*?.(LISTEN|ESTABLISHED)
OS = Solaris 10
The purpose of this regex is to match the ports in output of "netstat -an" and report if any ports between 6000-6009 are getting used. The only problem is if I have something like this (sample output as mentioned below), the regex matches everything with 6000 in it. It matches 46000, 60006 and 6000. Because of that we are getting faulty alerts. How can we fix this to just ONLY pick up ports (6000-6009)? Please help.
10.10.10.10.2055 10.10.4.10.60006 49552 0 49552 0 ESTABLISHED
10.10.10.10.6360 10.10.4.10.6000 65290 0 49640 0 LISTEN
10.10.10.10.2044 10.10.4.10.46000 49552 0 49552 0 ESTABLISHED
Your '.' before 600 is matching any character not just '.' (why you got 46000) and you need to match for a space after 600x (why you got 60006)
\\*.*?([.]600[0-9]) .*?.(LISTEN|ESTABLISHED)
You can use awk to match only field 2 for port number pattern and last field for status:
awk '$NF ~ /(LISTEN|ESTABLISHED)/ && $2 ~ /\.600[0-9]/
given the following 2 lines of strings, for example :
May 22 00:46:38.340 prod-lab03c-rd1 fpc4 XETH(4/2): %PFE-6: Link 0 XFP: Low Rx power warning set
[May 24 11:24:28.299 LOG: Notice] MIC(0/1) link 1 SFP receive power low warning set
i would like to store in 3 variables the following numbers :
[1] the 1st number after the "(", it could be 1 or more digits
[2] the 1st number after the "/", it could be 1 or more digits
[3] the first number after the "(L|l)ink" word, it could be 1 or more digits
could you please assist me on this please ?
many thanks
To get the first number after the first (, we can use .*\((\d+). Then to get the first number after the /, we can use /(\d+)\). And then to get the first number after "link": [lL]ink (\d+). We put these together to get
^.*\((\d+)/(\d+)\).*[lL]ink (\d+)
The three numbers will be in the three groups
This works here
\((.*?)/(.*?)\).*?[Ll]ink (\d+)
Give your input it will give back
group 1 group 2 group 3
4 2 0
0 1 1
A full tested example in Perl :
#!/usr/bin/env perl
use strict;
use warnings;
my #a;
$a[0] = "May 22 00:46:38.340 prod-lab03c-rd1 fpc4 XETH(4/2): %PFE-6: Link 0 XFP: Low Rx power warning set\n";
$a[1] = "[May 24 11:24:28.299 LOG: Notice] MIC(0/1) link 1 SFP receive power low warning set";
foreach (#a) {
print "\$1=$1|\$2=$2|\$3=$3\n" if m!\((\d+)/(\d+)\).*?(?:L|l)ink\s+(\d+)!;
}
The output :
$1=4|$2=2|$3=0
$1=0|$2=1|$3=1
I need to add a parameter for each code and name, i tried using (.+) or (.*) for each number, but it didnt work. Each space means that is a different number and not every space has the same width. Example from this:
Abanda CDP 192 129 58 0 0 0 2 3 3
2.998 0.013 33.091627 -85.527029 2582661
To this:
Abanda CDP |code1=192 |code2=129 |code3=58 |code4=0 |code5=0 |code6=0 |code7=2 |code8=3 |code9=3
|code9=2.998 |code10=0.013 |code11=33.091627 |code12=-85.527029 |code13=2582661
Try ([0-9.-]+). The reason .+ doesn't work is because . matches whitespace as well. The reason you can't just use \S+ (non-spaces) is because you only want to match the numbers.