3
\$\begingroup\$

I have this regular expression that extracts guid and couple of other attributes like name, type and version. Please review the regex for any optimizations and improvements.

Strings are always in the pattern of

/publication/guid/type/name;version=1234

regex

(([a-f0-9]+\-)+[a-f0-9]+)\/(.*?)\/(.*?);version=(\d*)   

Test records

Extract bold pieces from string.

/publication/d40a4e4c-d6a3-45ae-98b3-924b31d8712a/collection/content1;version=1520623346833

Expected output:

  1. d40a4e4c-d6a3-45ae-98b3-924b31d8712a
  2. collection
  3. content1
  4. 1520623346833

/publication/d40a4e4c-d6a3-45ae-98b3-924b31d8712a/article/testContent;version=1520623346891

Expected output

  1. d40a4e4c-d6a3-45ae-98b3-924b31d8712a
  2. article
  3. testContent
  4. 1520623346891

Code

Language is F#, but the regex works in C# too. Furthermore, I would like to use the same regex in Node.js, so I would like the regex to be language agnostic.

let matchEntity (m: Match) =
    { id= m.Groups.[1].Value; eType = m.Groups.[3].Value; name= m.Groups.[4].Value; version = m.Groups.[5].Value}


let regex = new Regex("(([a-f0-9]+\-)+[a-f0-9]+)\/(.*?)\/(.*?);version=(\d*)")
matchEntity regex.Match "/publication/d40a4e4c-d6a3-45ae-98b3-924b31d8712a/collection/content1;version=1520623346833"

enter image description here

\$\endgroup\$
3
  • \$\begingroup\$ code added, language is c#, f# but it should be language agnostics, I use in nodejs too, the regex has to be generic, no specific language implementation required. \$\endgroup\$
    – App2015
    Mar 18 '18 at 5:31
  • \$\begingroup\$ It doesn't work for me on regexr \$\endgroup\$ Mar 18 '18 at 5:55
  • \$\begingroup\$ it works. i.stack.imgur.com/gyZnT.png \$\endgroup\$
    – App2015
    Mar 18 '18 at 6:09
4
\$\begingroup\$

TL;DR; list of adjustments:

  • .NET RegEx support named capture groups. make use of them.
  • Make use of the GUID format specification.
  • Simplify retrieval with non-capturing groups.
  • Make assumptions explicit in character classes. Prefer negated chargroups to non-greedy matching

I propose the following regular expression instead:

(?<guid>[a-f0-9]{8}(?:\-[a-f0-9]{4}){3}\-[a-f0-9]{12})\/(?<type>[^\/]+)\/(?<name>[^;]+);version=(?<version>\d*)

While this regex is somewhat longer it matches both examples in 62 steps (as opposed to 117). This may only seem like a minor improvement, but it's not all that happens:

This regex uses named capturing groups that allow a much more natural and clear pattern extraction. Instead of accessing groups by magic indices, you can access them by name and the construction of matchEntity is accomplished as follows:

let matchEntity (m: Match) =
    { id= m.Groups.["guid"].Value; 
      eType = m.Groups.["type"].Value;
      name= m.Groups.["name"].Value; 
      version = m.Groups.["version"].Value }

Last but not least this regex also does not match incorrect GUID specifications

\$\endgroup\$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.