PCRE Regex pattern to match 8 to 12 digits of length

203 Views Asked by At

I'm trying to write a PCRE Regex pattern to match only the numbers of length (8 or 9 or 12) while leaving the last 4 digits unmasked. Below is my written regex pattern.

/(?<=\D|^)(?=\d{8,12}\D|$)(\d{3})[\s,-]?\[\s,-]\K\d{4}|(?<=\D|^)(?=\d{12}|\d{9}\D|$)\d{5}/gmi

Reference Regex101 link : https://regex101.com/r/DukWNG/1 This link has the working test cases for understanding.

Right now it matches the first 5 digits only but for length 8 or 9 or 12, it should match all the digits except leaving the last 4 digits.

Test case :

  1. if the length of the number is 8, then it should match first 4 leaving the last 4 unmasked
  2. if the length of the number is 9, then it should match first 5 leaving the last 4 unmasked
  3. if the length of the number is 12, then it should match first 8 digits leaving the last 4 unmasked.

and it should also match if there is a "hyphen" or "comma" or "dash" or "space" between numbers. I'm stuck and not sure how to make this work. Any help would be really great.

2

There are 2 best solutions below

2
Oliver Hao On

((?:\d[-_ \.]*){4,5}|(?:\d[-_ \.]*){8})(?:\d[-_ \.]*){4}$

https://regex101.com/r/9WmkNz/1

1
Casimir et Hippolyte On

This pattern seems to make the job:

~
(?<d> [0-9] [-_ –.]* ){4} # subpattern definition

(?= 
    \g<d>{4} (?: \g<d> (?: \g<d>{3} )? )? # allowed digit sequences
    (?: \g<d>+ (*SKIP) (*F) )? # skip the substring if digits remain
)

\g<d>* (?= \g<d>{4} ) # backtrack until there're 4 digits at the end
~ux

demo

Feel free to define yourself how eventual separators should exactly look like.

Interesting thing about this pattern, it doesn't need to be anchored at the start (with ^ or a lookbehind) since there are already two constraints:

  • the four digits at the start and the four other digits in the lookahead (that discards sequences with less than 8 digits)
  • and the \g<d>+ (*SKIP) (*F) control verbs combo that jumps after the remaining digits when the sequence doesn't match (with 8, 9 or 12 digits).