PatternRegex

Match IP:port

Pull an IPv4 address plus its port out of logs, configs and connection strings — the host:port shape nginx, Redis and half of devops config files use.

Last updated

Patterng
\b(?:\d{1,3}\.){3}\d{1,3}:\d{1,5}\b
Open in Regex Tester & Builder

Matches

  • Server listening on 192.168.1.10:8080 for requests
  • connect to 10.0.0.1:443 now
  • edge case 999.999.999.999:99999 unvalidated

Doesn’t match

  • The IP address 192.168.1.10 alone
  • example.com:8080 uses a hostname, not an IP

Why it’s written this way

(?:\d{1,3}\.){3}\d{1,3} repeats a one-to-three-digit octet and a literal dot three times, then a final octet — the same shape as the email and URL patterns elsewhere in this library, just without a domain on the end. The colon and \d{1,5} after it capture the port, allowing anything from a single digit up to five.

Word boundaries on both ends keep the match from starting mid-number inside a longer digit run, so it lines up cleanly against punctuation and whitespace in log lines and config files.

Edge cases to know

  • →Octets are not range-checked, so 999.999.999.999 matches even though no such address exists — this is a shape matcher, not a validator.
  • →The port is only checked for digit count, not range, so :99999 passes even though valid ports stop at 65535.
  • →It has no idea about IPv6 — bracketed addresses like [::1]:8080 need a different pattern entirely.

Part by part

\b
Word boundaries at each end, so the match cannot begin or end in the middle of a longer run of digits and dots.
(?:\d{1,3}\.){3}
Three repetitions of an octet followed by a dot — the first three quarters of the address, in one non-capturing group.
:
The literal colon separating host from port. No escaping needed; a colon has no special meaning in regex.
\d{1,5}
The port, one to five digits. Five is the maximum width of 65535, though the pattern does not check the value.

Common mistakes

  • \d+\.\d+\.\d+\.\d+:\d+

    Dropping the digit limits and boundaries matches version strings followed by a colon, so a log line reading "upgraded 192.0.2.4:see notes" registers as an endpoint.

    \b(?:\d{1,3}\.){3}\d{1,3}:\d{1,5}\b
  • \b(?:\d{1,3}\.){3}\d{1,3}:\d+\b

    An unbounded port length accepts a ten-digit number, which no TCP stack can represent. The five-digit cap will not catch 99999 but it does stop the match running away into an adjacent identifier.

  • \b(?:\d{1,3}\.){3}\d{1,3}(:\d{1,5})?\b

    Making the port optional turns this into a plain IPv4 pattern that sometimes captures a port, so a bare address matches and downstream code that assumes a port gets undefined.

Questions

Does it validate the port range?

No. Five digits allows anything up to 99999, and valid TCP ports stop at 65535. Parse the captured number and compare it if the distinction matters — expressing the range in the pattern itself is possible but unpleasant to read.

Will it match an IPv6 address with a port?

No. IPv6 endpoints wrap the address in square brackets precisely because it already contains colons, as in [2001:db8::1]:443. That is a different shape and needs its own pattern.

Does it check the address is valid?

Only its shape. 999.999.999.999:80 matches, because each octet is checked for digit count rather than value. This is a pattern for pulling endpoints out of logs, where the input is machine-generated.

How do I separate the host and port after matching?

Split on the last colon rather than the first, which keeps the logic identical if you later extend it to bracketed IPv6. Or add capture groups around the address and the port and read them directly from the match.

Related in Patterns