JON
JON

Reputation: 134

python re regex matching in string with multiple () parenthesis

I have this string

cmd = "show run IP(k1) new Y(y1) add IP(dev.maintserial):Y(dev.maintkeys)"

What is a regex to first match exactly "IP(dev.maintserial):Y(dev.maintkeys)"

There might be a different path inside the parenthesis, like (name.dev.serial), so it is not like there will always be one dot there.

I though of something like this: re.search('(IP\(.*?\):Y\(.*?\))', cmd) but this will also match the single IP(k1) and Y(y1

My usage will be:

If "IP(*):Y(*)" in cmd:
 do substitution of IP(dev.maintserial):Y(dev.maintkeys) to Y(dev.maintkeys.IP(dev.maintserial))

How can I then do the above substitution? In the if condition I want to do this change in order: from IP(path_to_IP_key):Y(path_to_Y_key) to Y(path_to_Y_key.IP(path_to_IP_key)) , so IP is inside Y at the end after the dot.

Upvotes: 0

Views: 114

Answers (3)

OTheDev
OTheDev

Reputation: 2967

Something like this?

r"IP\(([^)]*\..+)\):Y\(([^)]*\..+)\)"

You can try it with your string. It matches the entire string IP(dev.maintserial):Y(dev.maintkeys) with groups dev.maintserial and dev.maintkeys.

The RE matches IP(, zero or more characters that are not a closing parenthesis ([^)]*), a period . (\.), one or more of any characters (.+), then ):Y(, ... (between the parentheses -- same as above), ).

Example Usage

import re

cmd = "show run IP(k1) new Y(y1) add IP(dev.maintserial):Y(dev.maintkeys)"

# compile regular expression
p = re.compile(r"IP\(([^)]*\..+)\):Y\(([^)]*\..+)\)")

s = p.search(cmd)
# if there is a match, s is not None
if s:
    print(f"{s[0]}\n{s[1]}\n{s[2]}")
    a = "Y(" + s[2] + ".IP(" + s[1] + "))"
    print(f"\n{a}")

Above p.search(cmd) "[s]can[s] through [cmd] looking for the first location where this regular expression [p] produces a match, and return[s] a corresponding match object" (docs). None is the return value if there is no match. If there is a match, s[0] gives the entire match, s[1] gives the first parenthesized subgroup, and s[2] gives the second parenthesized subgroup (docs).

Output

IP(dev.maintserial):Y(dev.maintkeys)
dev.maintserial
dev.maintkeys

Y(dev.maintkeys.IP(dev.maintserial))

Upvotes: 1

Shana Cote
Shana Cote

Reputation: 36

This should work as it is more restrictive. (IP\([^\)]+\):Y\(.*?\))

[^\)]+ means at least one character that isn't a closing parenthesis.

.*? in yours is too open ended allowing almost anything to be in until "):Y("

Upvotes: 2

The fourth bird
The fourth bird

Reputation: 163277

You can use 2 negated character classes [^()]* to match any character except parenthesis, and omit the outer capture group for a match only.

To prevent a partial word match, you might start matching IP with a word boundary \b

\bIP\([^()]*\):Y\([^()]*\)

Regex demo

Upvotes: 1

Related Questions