You can accomplish this with either of the following regex patterns:
^(?:.*(A\d{3})|.*(B\d{3})) # pattern 1
^(?:.*(?=A)|.*(?=B))([AB]\d{3}) # pattern 2
Pattern 1
Regex
Pros/Cons: Easy, but uses two capture groups
^(?:.*(A\d{3})|.*(B\d{3}))
How this works:
^ anchors it to the start of the string
(?:.*(A\d{3})|.*(B\d{3})) match either of the following options
.* matches any character (except newline characters) any number of times (it's greedy so it'll match as much as possible)
(A\d{3}) matches A followed by 3 digits
The second options is the same as the first, but this works with backtracking:
^(?:.*(A\d{3})|.*(B\d{3}))
hello B123 A456
^ # anchor to the start of the string (to the location before the h)
# now attempt option 1 of the alternation: .*(A\d{3})
.* # match any character any number of times (greedy)
hello B123 A456 # this is what we currently match
# now backtrack to find A\d{3}
hello B123 A # we found A, check to see if \d{3} matches
hello B123 A456 # pattern fulfilled; result you're looking for in group 1
Code
s = ["hello A123 B456","hello B123 A456", "hello B123"]
r = /^(?:.*(A\d{3})|.*(B\d{3}))/
for (x of s) {
m = x.match(r)
if (m)
console.log(m[1] || m[2])
}
Pattern 2
Regex
Pros/Cons: Less comprehensible, but uses only one capture group
^(?:.*(?=A)|.*(?=B))([AB]\d{3})
How this works:
^ anchors it to the start of the string
(?:.*(?=A)|.*(?=B)) match either of the following options
.* matches any character (except newline characters) any number of times (it's greedy so it'll match as much as possible)
(?=A) ensures A follows the current position
- The second alternation is the same as above, but uses
(?=B) instead
([AB]\d{3}) match A or B followed by 3 digits
Code
s = ["hello A123 B456","hello B123 A456", "hello B123"]
r = /^(?:.*(?=A)|.*(?=B))([AB]\d{3})/
for (x of s) {
m = x.match(r)
if (m)
console.log(m[1])
}
^(?:.*(A\d{3})|.*(B\d{3}))