Community

    • Login
    • Search
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

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

    Help wanted · · · – – – · · ·
    4
    5
    67
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • James Norton
      James Norton last edited by James Norton

      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!

      Alan Kilborn 1 Reply Last reply Reply Quote 0
      • Alan Kilborn
        Alan Kilborn @James Norton last edited by

        @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. :-)

        James Norton 1 Reply Last reply Reply Quote 2
        • James Norton
          James Norton @Alan Kilborn last edited by

          @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.

          1 Reply Last reply Reply Quote 0
          • Terry R
            Terry R last edited by

            @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

            1 Reply Last reply Reply Quote 2
            • guy038
              guy038 last edited by guy038

              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

              1 Reply Last reply Reply Quote 2
              • First post
                Last post
              Copyright © 2014 NodeBB Forums | Contributors