Difficulty with using backreferences/capture groups in find/replace.



  • I have a regex that matches any IPv4 Address in a router’s BGP summary output and everything from “Established” and beyond. This is to isolate the AS number, and then ideally replace the text to the left of it with a router command, and the text to the right of it with more specific arguments for said command.
    My find regex:

    (((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\s+)(\s+Established.*)
    

    My replace regex (not working as I expect):

    ?1show ip bgp neighbor ?2 statistics detail
    

    Example output

    Neighbor  AS Number   Status        Time         Accepted Rejected  Sent  Queued
    1.2.3.4   12345       Established   0d 8h 56m    4823     982      1     0        
    

    What I want to happen:

    show ip bgp neighbor 12345 statistics detail
    

    What actually happens:

    show ip bgp neighbor  statistics detail12345
    

    I did some reading on the docs for regex replacement and I can’t quite figure out what I’m doing wrong. Any help/clarification is much appreciated!



  • @James-Norton

    Is your “Example output” section is really supposed to be example input?

    If so, I can’t get your regex to match it.

    Your use of ?1 and ?2 in the replace is confusing; probably you want \1 or my preference of ${1} (and of course \2 or ${2} for the second one).

    Otherwise, hard to say, but I’m sure someone else will come along and put some time into it. :-)



  • @Alan-Kilborn
    The row above the IP address are just the names of the columns, not intending to match on those. And my apologies, was missing the | before the “Established” capture group:

    (((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\s+)|(\s+Established.*)
    

    And the issue with using the referenced notation is it doesn’t replace the full IP address before it for some reason. If I use either \n or ${n} then I get this:

      1.2.3.4   show ip bgp neighbor 3. statistics detail12345show ip bgp neighbor  statistics detail
    

    My notation is likely wrong, I’m not programmer or regex master. But I’m essentially trying to say “From beginning of line to whitespace after IP address, replace with X. Then, from whitespace before “Established” and to the end of the line, replace with Y.”
    Hope that makes sense, thanks for taking a look.



  • @James-Norton said in Difficulty with using backreferences/capture groups in find/replace.:

    But I’m essentially trying to say “From beginning of line to whitespace after IP address, replace with X. Then, from whitespace before “Established” and to the end of the line, replace with Y.”

    I’m not sure why you need such a complicated regex just to identify the IP address, unless you have many and only want to work on defined ranges that might occur. A more generalised regex for IP address is \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} and as you state “…that matches any IPv4 Address…” I would think my regex should suffice.

    A possible solution might be (using the Replace function)
    Find What:(?-s)^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\x20+)(\d+\x20)(\x20+Established.*)
    Replace With:show ip bgp neighbor \2 statistics detail

    I could have even removed the ( and ) around the portions we don’t need as we don’t return those in the replacement.

    Terry



  • Hello, @james-norton, @alan-kilborn, @terry-r and All,

    BTW, note that there’s an important difference between :

    • To search for IPV4 addresses, in a file containing valid IVP4 addresses, only

    • To search for valid IPV4 addresses, in a file which may contain some non valid IPV4 addresses !


    In the first case, as the @terry-r’s solution, simply use the almost obvious regex \b(\d{1,3}\.){3}\d{1,3}\b

    In the second cas, use one of the two regexes, below :

    • (25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(*FAIL)|\b((?1)\.){3}(?1)\b

    • (?(DEFINE)(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))\b((?1)\.){3}(?1)\b


    Notes :

    • In the first regex, once the part (25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d) is stored as group 1, the (*FAIL) control verb discards this match but this regex part can be re-used with the syntax (?1). Then, the second alternative \b((?1)\.){3}(?1)\b does match a valid IPV4 address !

    • The second regex uses a special conditional syntax with the key expression (DEFINE). which stores, as above, the part 25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d, between parentheses, but which is never matched, by definition. So the effective regex is just the part \b((?1)\.){3}(?1)\b, coming next, which match valid IPV4 addresses only

    Best Regards,

    guy038


Log in to reply