DNS 호스트 이름 또는 IP 주소와 일치하는 정규식?


369

누구나 합법적 인 DNS 호스트 이름 또는 IP 주소와 일치하는 정규식이 있습니까?

95 %의 시간 동안 작동하는 것을 작성하는 것은 쉽지만 DNS 호스트 이름에 대한 최신 RFC 사양과 정확히 일치하도록 잘 테스트 된 것을 얻고 자합니다.

답변:


535

다음 정규식을 개별적으로 사용하거나 공동 OR 식으로 결합하여 사용할 수 있습니다.

ValidIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";

ValidHostnameRegex = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$";

ValidIpAddressRegex 는 유효한 IP 주소 및 ValidHostnameRegex 유효한 호스트 이름 과 일치합니다 . 사용하는 언어에 따라 \로 이스케이프해야 할 수도 있습니다.


ValidHostnameRegexRFC 1123에 따라 유효합니다 . 원래 RFC 952 는 호스트 이름 세그먼트를 숫자로 시작할 수 없도록 지정했습니다.

http://en.wikipedia.org/wiki/Hostname

RFC 952 에서 호스트 이름의 원래 사양은 레이블이 숫자 나 하이픈으로 시작할 수 없으며 하이픈으로 끝나서는 안된다고 규정했습니다. 그러나 후속 스펙 ( RFC 1123 )은 호스트 이름 레이블을 숫자로 시작하도록 허용했습니다.

Valid952HostnameRegex = "^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$";

3
여기 : stackoverflow.com/questions/4645126/…- 숫자로 시작하는 이름도 유효한 것으로 간주됩니다. 또한 하나의 점만 의심스러운 문제입니다. 그것에 대해 더 많은 피드백을 얻는 것이 좋을 것입니다.
BreakPhreak

16
IPv6을 추가 할 수 있습니다. OP는 어떤 유형 의 주소를 지정하지 않았습니다 . (그런데, 여기 에서 찾을 수 있습니다 )
new123456

32
사람들이 코드에서 이것을 맹목적으로 사용하기 전에 완전히 정확하지는 않습니다. RFC2181은 무시합니다. "DNS 자체는 리소스 레코드를 식별하는 데 사용할 수있는 특정 레이블에 대해 하나의 제한 사항 만 적용합니다. 그 한 가지 제한은 레이블의 길이와 전체 이름과 관련이 있습니다. 한 레이블의 길이는 1과 63 옥텟. 전체 도메인 이름은 255 옥텟 (구분 기호 포함)으로 제한됩니다. "
루블

7
@UserControl : 비 라틴 (Punycoded) 호스트 이름은 먼저 ASCII 형식 ( éxämplè.com= xn--xmpl-loa1ab.com) 으로 변환 한 다음 유효성을 검사해야합니다.
Alix Axel

6
귀하의 호스트 이름 표현식이 일부 유효하지 않은 값과 일치합니다. 시도한 결과 123.456.789.0유효한 호스트 이름입니다.
lbarreira

62

smink 의 호스트 이름 정규식은 호스트 이름 내의 개별 레이블 길이에 대한 제한을 준수하지 않습니다. 유효한 호스트 이름 내의 각 레이블은 길이가 63 옥텟을 초과 할 수 없습니다.

ValidHostnameRegex = "^ ([a-zA-Z0-9] | [a-zA-Z0-9] [a-zA-Z0-9 \-] {0,61} [a-zA-Z0-9]) \
(\. ([a-zA-Z0-9] | [a-zA-Z0-9] [a-zA-Z0-9 \-] {0,61} [a-zA-Z0-9])) * $ "

첫 번째 줄 끝의 위의 백 슬래시는 긴 줄을 나누기위한 Unix 쉘 구문입니다. 정규 표현식 자체의 일부가 아닙니다.

한 줄에 정규 표현식 만 있습니다.

^ ([a-zA-Z0-9] | [a-zA-Z0-9] [a-zA-Z0-9 \-] {0,61} [a-zA-Z0-9]) (\. ([a-zA-Z0-9] | [a-zA-Z0-9] [a-zA-Z0-9 \-] {0,61} [a-zA-Z0-9])) * $

또한 호스트 이름의 총 길이가 255자를 초과하지 않아야합니다 . 자세한 내용은 RFC-952 및 RFC-1123을 참조하십시오.


6
탁월한 호스트 패턴. 아마도 언어의 정규식 구현에 달려 있지만 JS의 경우 아무것도 잃지 않고 짧게 조정 할 수 있습니다./^[a-z\d]([a-z\d\-]{0,61}[a-z\d])?(\.[a-z\d]([a-z\d\-]{0,61}[a-z\d])?)*$/i
Semicolon

31

유효한 IP 주소 를 일치 시키려면 다음 정규식을 사용하십시오.

(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}

대신에:

([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\.([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])){3}

설명

많은 정규식 엔진이 OR시퀀스 의 첫 번째 가능성과 일치합니다 . 예를 들어 다음 정규식을 시도하십시오.

10.48.0.200

테스트

차이 테스트 좋은나쁜


5
시작 ^와 끝 $를 잊지 마십시오. 0.0.0.999 또는 999.0.0.0과 같은 것이 일치합니다. ;)
andreas

1
문자열의 시작 ^과 끝 $이 유효하려면 예가 필요하지만 텍스트에서 IP를 검색하는 경우 사용하지 마십시오.
Alban

식별 한 의도하지 않은 '비 욕심'은 다른 호스트 이름 솔루션에도 적용됩니다. 다른 호스트가 전체 호스트 이름과 일치하지 않으므로 이것을 귀하의 답변에 추가하는 것이 좋습니다. 예를 들어, ([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*([a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]|[a-zA-Z0-9])(\.([a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])|[a-zA-Z0-9]))*
ergohack

편집 : 위의 경우 실패를 보는 +대신 끝에 사용 *하십시오.
ergohack

5

최상위 게시물을 편집 할 수없는 것 같습니다. 여기에 답변을 추가하겠습니다.

호스트 이름-쉬운 대답, egrep 예제 여기에서 http : //www.linuxinsight.com/how_to_grep_for_ip_addresses_using_the_gnu_egrep_utility.html

egrep '([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}'

이 경우는 8 진수 옥텟의 0과 254 (ip addres) 또는 255 (netmask)보다 큰 값을 고려하지 않습니다. 추가 if 문이 도움이 될 것입니다.

법률 dns 호스트 이름에 관해서는 (인터넷 인트라넷이 아닌) 인터넷 호스트 이름 만 검사하고 있다면 쉘 / PHP의 혼합을 다음과 같이 썼지 만 정규 표현식으로 적용 할 수 있습니다.

먼저 ietf 웹 사이트로 이동하여 법적 레벨 1 도메인 이름 목록을 다운로드하고 구문 분석하십시오.

tld=$(curl -s http://data.iana.org/TLD/tlds-alpha-by-domain.txt |  sed 1d  | cut -f1 -d'-' | tr '\n' '|' | sed 's/\(.*\)./\1/')
echo "($tld)"

.com .org 또는 .ca와 같이 최상위 도메인 이름의 적법성을 검사하는 멋진 코드가 제공됩니다.

그런 다음 여기에 나와있는 지침에 따라 표현식의 첫 부분을 추가하십시오 .http : //www.domainit.com/support/faq.mhtml?category=Domain_FAQ&question=9 옥텟의 시작 또는 끝.

(([a-z0-9]+|([a-z0-9]+[-]+[a-z0-9]+))[.])+

그런 다음이를 모두 정리하십시오 (PHP preg_match 예).

$pattern = '/^(([a-z0-9]+|([a-z0-9]+[-]+[a-z0-9]+))[.])+(AC|AD|AE|AERO|AF|AG|AI|AL|AM|AN|AO|AQ|AR|ARPA|AS|ASIA|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BIZ|BJ|BM|BN|BO|BR|BS|BT|BV|BW|BY|BZ|CA|CAT|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|COM|COOP|CR|CU|CV|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EDU|EE|EG|ER|ES|ET|EU|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GOV|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|INFO|INT|IO|IQ|IR|IS|IT|JE|JM|JO|JOBS|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MG|MH|MIL|MK|ML|MM|MN|MO|MOBI|MP|MQ|MR|MS|MT|MU|MUSEUM|MV|MW|MX|MY|MZ|NA|NAME|NC|NE|NET|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|ORG|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PRO|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|ST|SU|SV|SY|SZ|TC|TD|TEL|TF|TG|TH|TJ|TK|TL|TM|TN|TO|TP|TR|TRAVEL|TT|TV|TW|TZ|UA|UG|UK|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|XN|XN|XN|XN|XN|XN|XN|XN|XN|XN|XN|YE|YT|YU|ZA|ZM|ZW)[.]?$/i';

    if (preg_match, $pattern, $matching_string){
    ... do stuff
    }

확인하는 문자열이 256 자보다 짧은 지 확인하기 위해 if 문을 추가 할 수도 있습니다 ( http://www.ops.ietf.org/lists/namedroppers/namedroppers.2003/msg00964.html


1
"999.999.999.999"와 같은 가짜 IP 주소와 일치하기 때문에 -1입니다.
bdesham

1
"이 경우는 8 진수 옥텟의 0과 254 (ip addres) 또는 255 (netmask)보다 큰 값을 고려하지 않습니다."
Alex Volkov

네가 대답 할 자격이 있음을 알았어 귀하의 답변 중 그 부분이 여전히 유용하지 않기 때문에 하향 투표했습니다.
bdesham

3

표준 라이브러리에 내장되어있는 대부분의 언어를위한 라이브러리가 있습니다. 그리고 그 라이브러리는 4 년 전에 스택 오버플로 답변을 복사하고 잊어 버린 코드보다 훨씬 자주 업데이트 될 가능성이 큽니다. 물론 그들은 일반적으로 여러 그룹과 일치하는 대신 주소를 사용 가능한 형태로 구문 분석합니다.

예를 들어 (POSIX) C에서 IPv4 감지 및 구문 분석 :

#include <arpa/inet.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
  for (int i=1; i!=argc; ++i) {
    struct in_addr addr = {0};
    printf("%s: ", argv[i]);
    if (inet_pton(AF_INET, argv[i], &addr) != 1)
      printf("invalid\n");
    else
      printf("%u\n", addr.s_addr);
  }
  return 0;
}

예를 들어, 채팅 메시지에서 유효한 모든 주소를 찾으려고하면 이러한 기능이 작동하지 않습니다. 그러나 거기에서도 단순하지만 지나치게 정식적인 정규식을 사용하여 잠재적 인 일치 항목을 찾는 것이 더 쉬울 수 있습니다. 라이브러리를 구문 분석합니다.

예를 들어, 파이썬에서 :

>>> import ipaddress
>>> import re
>>> msg = "My address is 192.168.0.42; 192.168.0.420 is not an address"
>>> for maybeip in re.findall(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', msg):
...     try:
...         print(ipaddress.ip_address(maybeip))
...     except ValueError:
...         pass

2
def isValidHostname(hostname):

    if len(hostname) > 255:
        return False
    if hostname[-1:] == ".":
        hostname = hostname[:-1]   # strip exactly one dot from the right,
                                   #  if present
    allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
    return all(allowed.match(x) for x in hostname.split("."))

이 정규식을 설명해 주시겠습니까? 정확히, (?!-), (? <!-)은 무엇을 의미합니까?
Scit

1
@Scit, 정규식 엔진에서 사용할 수 있으면 "-"문자로 시작하거나 끝나지 않도록하십시오. 예를 들어 Python 또는 Perl .
YLearn

1

나는 이것이 최고의 IP 검증 정규식이라고 생각합니다. 한번 확인 해주세요 !!!

^(([01]?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))\.){3}([01]?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))$

1
"^((\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])\.){3}(\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])$"

1

유효한 IP 주소에서 작동합니다.

regex = '^([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-5][0-5])[.]([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-5][0-5])[.]([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-5][0-5])[.]([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-5][0-5])$'

1
/^(?:[a-zA-Z0-9]+|[a-zA-Z0-9][-a-zA-Z0-9]+[a-zA-Z0-9])(?:\.[a-zA-Z0-9]+|[a-zA-Z0-9][-a-zA-Z0-9]+[a-zA-Z0-9])?$/

0

다음은 Ant에서 ANT_OPTS에서 프록시 호스트 IP 또는 호스트 이름을 얻기 위해 사용한 정규 표현식입니다. 이것은 포크 IP에 대한 프록시를 구성하기 전에 Ant "isreachable"테스트를 실행할 수 있도록 프록시 IP를 얻는 데 사용되었습니다.

^.*-Dhttp\.proxyHost=(\w{1,}\.\w{1,}\.\w{1,}\.*\w{0,})\s.*$

그건있어 \w그것은 IP, 특정 상황에서만 호스트 이름을 캡처하지 않습니다, 바로 거기.
Yaron

0

IP 주소에 이것이 잘 작동한다는 것을 알았습니다. 그것은 최고 답변처럼 유효성을 검사하지만 ip가 격리되어 IP 뒤에 또는 앞에 텍스트 또는 더 많은 숫자 / 십진수가 없도록합니다.

(? <! \ S) (? : (? : \ d | [1-9] \ d | 1 \ d \ d | 2 [0-4] \ d | 25 [0-5]) \ b |. \ b) {7} (?! \ S)


나는 많이 시도했지만 여기서 2 가지를 이해할 수 없었습니다. 1. \ b는 단어 경계를 지정합니다. 왜 \ b를 사용합니까? 어느 경계입니까? 그리고 2. 왜 {7}에서만 작동합니까 내가 이해 한 바에 따르면, 그것이 {4} 여야한다고 생각하지만 작동하지 않습니다. 선택적으로 캡처하지 않은 블록을 사용하는 이유를 알 수 있습니다.
Srichakradhar


0

이 시도:

((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

내 경우에는 작동합니다.


0

IP 주소와 관련하여 선행 0을 포함할지 여부에 대한 논쟁이있는 것으로 보입니다. 한 번 일반적인 관행이었고 일반적으로 받아 들여 졌으므로 현재 환경 설정에 관계없이 유효한 것으로 표시 되어야 한다고 주장합니다 . 문자열 앞뒤의 텍스트를 확인 해야하는지 여부와 모호한 부분이 있습니다. 1.2.3.4는 유효한 IP이지만 1.2.3.4.5는 아니고 1.2.3.4 부분과 2.3.4.5 부분이 일치하지 않아야합니다. 다음과 같은 표현으로 일부 문제를 처리 할 수 ​​있습니다.

grep -E '(^|[^[:alnum:]+)(([0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])([^[:alnum:]]|$)' 

불행한 부분은 옥텟을 검증하는 정규 표현식 부분이 많은 솔루션에서 사실대로 반복된다는 사실입니다. 이것이 패턴의 인스턴스보다 낫지 만 서브 루틴이 사용되는 정규식에서 지원되는 경우 반복을 완전히 제거 할 수 있습니다. 다음 예는 -P스위치 를 사용하여 해당 기능을 활성화하고 grep미리보기 및 미리보기 기능을 활용합니다. (선택한 기능 이름은 옥텟의 경우 'o'입니다. 이름으로 '옥텟'을 사용할 수는 있지만 간결하고 싶었습니다.)

grep -P '(?<![\d\w\.])(?<o>([0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]))(\.\g<o>){3}(?![\d\w\.])'

점이 점 표기법의 일부가 아닌 마침표가 올 수 있기 때문에 IP 주소가 문장 형식의 텍스트가있는 파일에있는 경우 점을 처리하면 실제로 잘못된 부정이 발생할 수 있습니다. 위의 변형은 다음을 수정합니다.

grep -P '(?<![\d\w\.])(?<x>([0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]))(\.\g<x>){3}(?!([\d\w]|\.\d))'

0
>>> my_hostname = "testhostn.ame"
>>> print bool(re.match("^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$", my_hostname))
True
>>> my_hostname = "testhostn....ame"
>>> print bool(re.match("^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$", my_hostname))
False
>>> my_hostname = "testhostn.A.ame"
>>> print bool(re.match("^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$", my_hostname))
True

0

새로운 네트워크 프레임 워크에는 IP 주소 부분을 매우 쉽게 처리하는 struct IPv4Address 및 struct IPv6Address에 대한 실패한 초기화 프로그램이 있습니다. 정규식을 사용하여 IPv6에서이 작업을 수행하는 것은 모든 단축 규칙에 따라 어렵습니다.

불행히도 호스트 이름에 대한 우아한 대답이 없습니다.

네트워크 프레임 워크는 최신 버전이므로 최신 OS 버전으로 컴파일해야 할 수도 있습니다.

import Network
let tests = ["192.168.4.4","fkjhwojfw","192.168.4.4.4","2620:3","2620::33"]

for test in tests {
    if let _ = IPv4Address(test) {
        debugPrint("\(test) is valid ipv4 address")
    } else if let _ = IPv6Address(test) {
        debugPrint("\(test) is valid ipv6 address")
    } else {
        debugPrint("\(test) is not a valid IP address")
    }
}

output:
"192.168.4.4 is valid ipv4 address"
"fkjhwojfw is not a valid IP address"
"192.168.4.4.4 is not a valid IP address"
"2620:3 is not a valid IP address"
"2620::33 is valid ipv6 address"

-1

이건 어때요?

([0-9]{1,3}\.){3}[0-9]{1,3}

9999999999.0.0.9999999999 :) 그러나 대부분의 프로그래머에게는이 짧은 접근법으로 충분합니다.
andreas

3
이것은-센스없는 IP 주소 (@Shebuka 참고)와 일치하므로 -1입니다.
bdesham

-1

PHP에서 : filter_var(gethostbyname($dns), FILTER_VALIDATE_IP) == true ? 'ip' : 'not ip'


2
이 코드는 질문에 대답 할 수 있지만 일반적으로 코드 와 함께 설명 하면 대답이 훨씬 유용합니다. 제발 편집 답변을 어떤 맥락과 설명을 제공합니다.
user4642212

그리고 내가 실수하지 않으면 FILTER_VALIDATE_IP는 PHP 전용 값입니다.
DonGar

-2

mywebsite.co.in, thangaraj.name, 18thangaraj.in, thangaraj106.in 등과 같은 호스트 이름 확인

[a-z\d+].*?\\.\w{2,4}$

3
-1. OP는 "최신 RFC 사양과 정확히 일치하도록 테스트를 잘 마쳤습니다"라고 요청했지만 * .museum과는 일치하지 않지만 * .foo와 일치합니다. 유효한 TLD 목록다음과 같습니다 .
bdesham

나는 확실히는 문자 클래스 (대괄호) 안에 플러스를 넣어 좋은 아이디어입니다 아니에요, 또한, 5 개 문자 (와 TLD를가 .expert 예를 들어).
Yaron

RFC로 달성하는 가장 좋은 방법은 시스템 / 언어 기능을 사용하는 것입니다. inet_aton충분합니다.
m3nda 2016 년

-2

IP 주소 일치 \ d + [.] \ d + [.] \ d + [.] \ d +에 대한이 간단한 정규식 일치 패턴에 대해 생각했습니다.


1111.1.1.1은 유효한 IP가 아닙니다. 서브넷을 신경 쓰지 않으면 실제로 IP 형식을 테스트 할 수있는 방법이 없습니다. 적어도 ^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}올바른 방법이 아닌 비슷한 모양으로 외모 수에주의를 기울여야합니다 . 스크립트를 작성할 언어가있는 경우 네트워크 기능에 액세스 할 수 있습니다. REAL ip를 확인하는 가장 좋은 방법은 시스템에 올바른 형식으로 변환하고 ip하도록 지시 한 다음 true / false를 확인하는 것입니다. 파이썬의 경우을 사용 socket.inet_aton(ip)합니다. PHP의 경우 필요합니다 inet_aton($ip).
m3nda 2016 년

파이썬 사용자는 여기를 살펴볼 수 있습니다 : gist.github.com/erm3nda/f25439bba66931d3ca9699b2816e796c
m3nda
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.