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/…-数字で始まる名前も有効と見なされることを説明します。また、問題のあるドットは1つだけです。それについてもっとフィードバックがあれば素晴らしいと思います。
BreakPhreak 2011年

16
IPv6を追加することもできます。OPは、どのタイプのアドレスを指定しませんでした。(ちなみに、ここで見つけることができます
new123456 '27 / 02/27

32
人々が盲目的にコードでこれを使用する前に、完全に正確ではないことに注意してください。RFC2181は無視されます。「DNS自体は、リソースレコードの識別に使用できる特定のラベルに1つの制限のみを課します。その1つの制限は、ラベルの長さとフルネームに関係しています。1つのラベルの長さは、 1および63オクテット。完全なドメイン名は、255オクテット(区切り文字を含む)に制限されています。
2013

7
@UserControl:ラテン語ではない(Punycoded)ホスト名は、最初にASCII形式(éxämplè.com= xn--xmpl-loa1ab.com)に変換してから検証する必要があります。
Alix Axel

6
ホスト名の式がいくつかの無効な値と一致しています:試したところ123.456.789.0、有効なホスト名であると表示されました
lbarreira 2014

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
セミコロン

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
start ^とend $を忘れないでください。0.0.0.999や999.0.0.0なども一致します。;)
andreas 2013年

1
はい、文字列を有効にするにはstart ^とend $が必要ですが、IPをテキストに検索する場合は使用しないでください。
2013年

あなたが特定した意図しない「貪欲さ」は、他のホスト名ソリューションにも適用されます。他のものは完全なホスト名と一致しないため、これを回答に追加する価値があります。例:([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 2017

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}'

ただし、最初のオクテットの0などの値や、254(ipアドレス)または255(ネットマスク)より大きい値は考慮されません。追加のifステートメントが役立つかもしれません。

正当なdnsホスト名については、インターネットのホスト名のみをチェックし(イントラネットはチェックしない)、シェル/ phpを組み合わせた次のコードを書きましたが、正規表現として適用できるはずです。

最初にietf Webサイトにアクセスし、有効なレベル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などのトップドメイン名の合法性をチェックする素晴らしいreコードが得られます。

次に、ここにあるガイドラインに従って式の最初の部分を追加します-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アドレスに一致するためです。
bdesham 2014

1
「ケースでは、最初のオクテットの0のような値、および254(IPアドレス)または255(ネットマスク)より大きい値は考慮されていません。」
Alex Volkov 14

はい、あなたはあなたの答えを修飾したのを見ました。あなたの回答のその部分はまだ役に立たないので、私は反対票を投じました。
bdesham 2014

3

これを行うほとんどの言語用のライブラリがあり、多くの場合、標準ライブラリに組み込まれていることに注意してください。そして、それらのライブラリーは、4年前にStack Overflowの回答からコピーして忘れたコードよりもはるかに頻繁に更新される可能性があります。そしてもちろん、彼らはまた、単にグループとの一致を与えるだけでなく、アドレスを何らかの使用可能な形式に解析します。

たとえば、(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;
}

明らかに、たとえば、チャットメッセージですべての有効なアドレスを見つけようとすると、そのような関数は機能しません。それらを解析するライブラリ。

たとえば、Pythonの場合:

>>> 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])$'


0

これは、ANT_OPTSからプロキシホストIPまたはホスト名を取得するためにAntで使用した正規表現です。これは、プロキシーIPを取得するために使用されたため、分岐したJVMのプロキシーを構成する前にAntの「到達可能」テストを実行できました。

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

その\wとおりです。IPはキャプチャされません。特定の状況でのホスト名のみがキャプチャされます。
Yaron、2014

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、2013


0

これを試して:

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

私の場合はうまくいきます。


0

IPアドレスに関しては、先行ゼロを含めるかどうかについていくつかの議論があるようです。これはかつて一般的な慣行であり、一般に受け入れられているため、現在の好みに関係なく、有効であるとフラグを立てる必要があると私は主張します。文字列の前後のテキストを検証する必要があるかどうかについてもあいまいさがあり、繰り返しますが、そうする必要があります。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 2013年

3
-1は、@ Shebukaがメモしているように、ナンセンスなIPアドレスに一致するためです。
bdesham 2014

-1

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


2
このコードは質問に答えることがありますが、一般的にコードと一緒説明することで、答えがはるかに役立ちます。してください編集あなたの答えをして、いくつかのコンテキストと説明を提供します。
user4642212 2016年

そして、私が間違っていない限り、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 2014

プラスを文字クラス(角かっこ)の中に入れるのは良い考えだとは思いません。さらに、5文字のTLD(たとえば.expert)があります。
Yaron、2014

RFCで達成する最良の方法は、システム/言語機能を使用することです。inet_aton十分です
m3nda 2016年

-2

私は、\ d + [。] \ d + [。] \ d + [。] \ d +に一致するIPアドレスのこの単純な正規表現一致パターンについて考えました


1111.1.1.1は有効なIPではありません。サブネットに注意しないと、IP形式を実際にテストする方法はありません。あなたは少なくとも似たような外観の数に注意する必要が^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}あり、もちろんそれは正しい方法ではありません。スクリプトを記述する言語を持っている場合は、そのネットワーク機能に確実にアクセスできます。REAL ipをチェックする最良の方法は、システムに変換して正しい形式に変換するようにシステムに指示し、true / falseをチェックすることです。Pythonの場合はを使用しますsocket.inet_aton(ip)。PHPの場合uが必要inet_aton($ip)です。
m3nda 2016年

Pythonユーザーはこちらをご覧ください:gist.github.com/erm3nda/f25439bba66931d3ca9699b2816e796c
m3nda
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.