Using a regex to identify EQUIPMENTID numbers - VBA

Viewed 60

Struggling trying to construct a Regexp to identify equipment numbers, I require this to identify equipment numbers in multiple formats including pooled equipment numbers e.g AFD21101 or AFD21101-02-03 or AFD21101-2-3 including various prefixes as per testdata.

Any tips or feedback welcome, possibly it may be easier with multiple RegExp for each scenario but I had hopped to have a master that would identify any of these patterns and be able to extract from a string for further process in a more detailed order. Possibly converting to Long format etc.

Any assistance is greatly appreciated. Hopefully I can return the favour.

What I've tried so far:

^[abcpfsmschafddfcpdcdplldt][glvmdugmrxftiichlewsnuabn][mmrprbdpucdsxtvuwcrslbubk][0-9][0-9xX][0-9xX][0-9xX][0-9xX]|[0-9xX-][0-9]|[0-9]

^[abcpfsmschafddfcpdcdplldt][glvmdugmrxftiichlewsnuabn][mmrprbdpucdsxtvuwcrslbubk][0-9][0-9xX][0-9xX][0-9xX][0-9xX]

^(BLM)|(SUB)|

(CVR)|FDR|SMP|CRU|HXC|ATS|AFD|FTS|DIX|DIT|FIT|FCV|KV|FV|CHU|PLW|BCR|DEC|CTR|CWR|V|DSS|PNL|MTR|LUB|LAU|CCL|DBB|TNK|THK|PIT|[0-9][0-9xX][0-9xX][0-9xX][0-9xX]

Testdata - will have to handle multiple separated by comma or multiline as per testdata examples below

// Example test data 1: (CSV+)
CRN21003 (CB-3), CRN21004 (CB-4)

// Example test data 2: (CSV)
CVR21404, CHU21437, AFD21401

// Example test data 3: (Multi-line)
MGD22401 - 16
DEC22401 - 16

// Example test data 4: (In string)
AFD11122 SOME OTHER RANDOM DATA WDC11121_22 SOME OTHER RANDOM DATA 

//Additional matches
AFD21101-03
AFD21101_03
AFD21101-02-03
AFD21101_02_03
AFD21101-2-3
AFD21101_2_3
FDR21407-08
BLM21401
SUB21601
CVR21601
Fdr21601
SMP21501
CRU21501
HXC21501
AFD21501
FTS21X01
DIX21301
DIT22501
FIT21X0X
FCV21501

Pattern:

  1. Base is max 8 digits

    1. 1-3 letters (A-Z)
    2. 5 Digits (0-9) including X as wildcard
  2. Followed by pooled EQUIPMENT ID's

     e.g. AFD21101-2-3, AFD21101-02-03 or AFD21101_02_03
    
    1. _ or - are delimiters indicating abbreviated subsequent equipment id's or ranges.
    2. AFD21101-02-03 is equivalent to AFD21101, AFD21102, AFD21103 in full form

Possible Prefix's continued

KV
CHU
PLW
BCR
DEC
CTR
CWR
V
DSS
PNL
MTR
LUB
LAU
CCL
DBB
TNK
THK
PIT
AGM2XXXX - valid

Some Invalid matches would be something like

AGM211011 or AGMXXXXX or 21101 or 2110 or AGM21101-094-034 or AGM (prefix only without a trailing 5 digit number/ X wildcard)

3 Answers

If I understand your issue, you need to get the strings which starts with substring provided and contains numbers.

You could try the following regex.

^(?:BLM|SUB|CVR|FDR|SMP|CRU|HXC|ATS|AFD|FTS|DIX|DIT|FIT|FCV|KV|FV|CHU|PLW|BCR|DEC|CTR|CWR|V|DSS|PNL|MTR|LUB|LAU|CCL|DBB|TNK|THK|PIT)[0-9_-]+

Details:

  1. ^: start of string
  2. ?:: non capturing group
  3. (?:BLM|SUB|CVR|FDR|SMP|CRU|HXC|ATS|AFD|FTS|DIX|DIT|FIT|FCV|KV|FV|CHU|PLW|BCR|DEC|CTR|CWR|V|DSS|PNL|MTR|LUB|LAU|CCL|DBB|TNK|THK|PIT): list of prefixes.

Demo

It isn't 100% clear what you're intending to do because:

  1. The test data you've supplied is comprised wholly of expected matches
  2. The expected output is unclear. Although this largely relays back to point 1!

However, there are many ways of getting the information you require. They all depend on how your source data is organised though...

//  Example test data 1:

AFD11122 SOME OTHER RANDOM DATA
WDC11121_22 SOME OTHER RANDOM DATA

//  Example test Data 2:

SOME RANDOM DATA AFD11122 AND SOME MORE RANDOM DATA WDC11121_22 WITH SOME MORE

Assuming that the data is at the start of the string AND that you want to capture each string as a whole:

// Option 1
/^(.*?)\s/
 ^            : Start of string
  (.*?)       : Non-greedy capture group
       \s     : First space (first because the capture group was non-greedy)

// Option 2
/^([ABCDEFHIKLMNPRSTUVWX][ABCDEFHILMNRSTUVWX]?[BCDKLMPRSTUVWX]?[x\d]{5}[_\-\d]*)/i
 ^                                                                                    : Start of string
  (                                                                                   : Start of capture group
   [ABCDEFHIKLMNPRSTUVWX]                                                             : Capture any letter in character set
                         [ABCDEFHILMNRSTUVWX]?                                        : OPTIONALLY [?] capture any letter in character set
                                              [BCDKLMPRSTUVWX]?                       : OPTIONALLY [?] capture any letter in character set
                                                               [x\d]{5}               : Capture any number or x 5 times
                                                                       [_\-\d]*       : Capture any number, hyphen, or underscore until you reach a character not in the set
                                                                               )      : End of capture group
                                                                                 i    : FLAG - case insensitive

// Option 3
/^((?:AFD|BCR|BLM....TNK|V)[\d_\-]*)/i
 ^                                         : Start of string
  (                                        : Start of capture group
   (?:                                     : Start of non-capturing group
      AFD|BCR|BLM....TNK|V                 : List of prefixes separated with "|"
                          )                : End of non-capturing group
                           [\d_\-]*        : Capture any number, hyphen, or underscore until you reach a character not in the set
                                   )       : End of capture group
                                      i    : FLAG - case insensitive

// Option 4
/^([a-z]{1,3}[x\d]{5}[_\-\d]*)/i    :
 ^                                  : Start of string
  (                                 : Start of capture group
   [a-z]{1,3}                       : Capture any letter [range: a-z] 1 to 3 times {1,3}
             [x\d]{5}               : Capture any number [\d] or x [x] 5 times {5}
                     [_\-\d]*       : Capture any number, hyphen, or underscore until you reach a character not in the set
                             )      : End of capture group
                               i    : FLAG - case insensitive

Based on your updates to the main question I would stick with option 4 unless you specifically need to make sure that only the set prefixes are matched.

In the event that your data looks more like Example Data 2 then the above expressions will need to be altered accordingly; some examples below:

/([a-z]{1,3}[x\d]{5}[_\-\d]*)/i        : Remove the ^
/\b([a-z]{1,3}[x\d]{5}[_\-\d]*)/i      : Add a word boundary to the start of the expression
/[^a-z]([a-z]{1,3}[x\d]{5}[_\-\d]*)/i  : Start the expression with anything BUT a letter

How you alter it will depend on the data that you're searching through.

Updated RegEx based on latest question edits

/([a-z]{1,3}(?!xxxxx)[x\d]{5}(?!\d)[_\-\d]*)/ig

Try this:

[A-Z]{1,3}[\dX]{5}([_-])0?\d(\10?\d)?

This requires the separator to be the consistent, ie either both - or both _, by capturing the separator and using a back reference to it \1, although the second “pooled ID” is optional.

As far as I can tell, this matches all of your examples.

Related