Question

So I have something like this:

\b(0?[1-9]|[1-2][0-9]|3[0-6])\b

Which works fine for only matching numbers 1-36. But I might get something like S36, which won't get matched. I can't assume a clean word boundary on either side of the number.

I'd like to have it so it'll match 1-36 with anything except other numbers on either side.

I thought something like this would work, but it doesn't:

(?<=\D)(0?[1-9]|[1-2][0-9]|3[0-6])(?=\D)

It's supposed to be a positive look-behind at the start to make sure there is anything but digits preceding the number and a positive look-ahead after the number to make sure the same is true following it.

What is the correct way of doing this?

Was it helpful?

Solution

If your engine doesn't support lookbehind/lookahead, then you can still just match the whole thing including the non-digits and pick the capture you're interested in.

(?:^|[^1-9])(0?[1-9]|[1-2][0-9]|3[0-6])(?:$|[^1-9])

Your result would be in capture 1 in this example (the "outer" matches are in non-capturing groups).

Note that with .NET, you do have full support for lookbehind and lookahead, so that the following should work:

(?<![0-9])(?:0?[1-9]|[1-2][0-9]|3[0-6])(?![0-9])

This uses negative lookaround instead of positive lookaround. Otherwise, numbers that are at the beginning or end of the string will not match because a non-numeric character is required where there is no character, leading to a non-match.

OTHER TIPS

You can just use [^0-9] at the beginning and the end and then get the number by looking at the appropriate captured group ( second in this case ):

(^|[^0-9])(0?[1-9]|[1-2][0-9]|3[0-6])($|[^0-9])
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top