Regex, capture one or more 6-digit numbers AFTER specific pattern

Viewed 117

my first question, so bear with me should anything no quite right. (I have read all topics suggested after entering title, but still no luck)

In words I need to capture all (i.e. one or more) 6-digits numbers following after specific keyword (here: "Customer\s"), which begins with 14 or 15

Input string:

Part Numbe

Customer PO

Description

Cust Part No: 325386

EB011036 // 175663/147667/8 ECK

5500003766 / 148266 -

WALK

between the start keyword to look after, and the following suitable 6 digit pattern any signs can be placed.

What I have come up so far: Since the string can contain return, new lines etc. I set the (?s) flag before:

Then a positive lookbehind:

(?s)(?<=Customer )

followed by

.+?

and then

(\D(1(4|5)\d{4})\D)+

So the whole expression:

(?<=Customer ).*?(\D(1(4|5)\d{4})\D)+

https://regex101.com/r/FEKwcY/1

But this only finds the first instance (147667) after Customer, not the second or more following. If I change the wildcard between the groups to gready, it will find the last one, but not the first possible one.

Having played around further I added an alternation in the pos. lookbehind group:

(?s)(?<=Customer |\D\d{6}\D).*?(\D(1(4|5)\d{4})\D)+

This in fact find the two, but I am afraid, that this will also find before the Customer keyword.

2 Answers

You can use

(?s)(?<=\bCustomer\b.*?)\b1[45]\d{4}\b

See the .NET regex demo. Details:

  • (?s) - RegexOptions.Singleline inline modifier flag
  • (?<=\bCustomer\b.*?) - a positive lookbehind that matches a location that is immediately preceded with Customer as a whole word and then any zero or more chars as few as possible
  • \b - a word boundary
  • 1 - a 1 char
  • [45] - 4 or 5
  • \d{4} - any four digits
  • \b - a word boundary

PS demo:

PS C:\Users\admin> $s = "Part Number`r`n`r`nCustomer PO`r`n`r`nDescription`r`n`r`nCust Part No: 325386`r`n`r`nEB011036 // 175663/147667/8 ECK`r`n5500003766 / 148266 -`r`n`r`nWALK"
PS C:\Users\admin> Select-String '(?s)(?<=\bCustomer\b.*?)\b1[45]\d{4}\b' -input $s -AllMatches | Foreach {$_.matches.value}
147667
148266

I feel like this is more of a communal given answer as both @WiktorStribiżew and @TheFourthBird had relevant contributions that lead to the following pattern that should work in PowerShell's .Net regex flavor:

(?:^.*?\bCustomer\b|\G(?!^)).*?\b(1[45]\d{4})\b

See an online demo.

  • (?: - Open non-capture group:
    • ^.*?\bCustomer\b - Start string anchor followed by 0+ characters (lazy) upto "Customer" inside word-boundaries.
    • | - Or:
    • \G(?!^) - Assert position at position of previous match and explicitly avoid to match the start of the string.
    • ) - Close non-capture group.
  • .*?\b - 0+ Characters (lazy) upto a word-boundary.
  • (1[45]\d{4}) - A capture group that start a substring with a 1 followed by either a 4 or 5 and 4 other random digits.
  • \b - Another word-boundary.
Related