0* (?: 1\d? | 2 (?: [0-4]\d? | 5[0-5]? ) ) (?: (?: # since we got here, the first 1-3 digits formed a number < 256 # so allow a dot \. # a near-copy of the surrounding regex goes here to match next octet ) | # no dot matched: allow digit-only strings forming numbers up to 2**32-1 # (and remember we might already have matched up to 3 digits!) # this bit needs adjusting to smaller ranges in the nested copies )