正規のDNSホスト名またはIPアドレスに一致する便利な正規表現はありますか?
95%動作するものを書くのは簡単ですが、私はDNSホスト名の最新のRFC仕様に正確に一致するようによくテストされたものを手に入れることを望んでいます。
次の正規表現は、単独で使用することも、結合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は有効なホスト名を照合します。使用する言語によっては、\を\でエスケープする必要があります。
ValidHostnameRegexは、 RFC 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])$";
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を参照してください。
一番上の投稿を編集できないようですので、ここに回答を追加します。
ホスト名 - 簡単な答え、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 addres)または255(netmask)より大きい値は考慮されません。追加のifステートメントが役に立つかもしれません。
インターネットのホスト名(イントラネットではない)だけをチェックしていれば、法的なdnsホスト名に関しては、私は次の断片を書きました。Shell/ 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のように、トップドメイン名の合法性をチェックするコードを作成し直してください。
それからここにあるガイドラインに従って式の最初の部分を追加してください - 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
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("."))
注目に値するのは、これを行うほとんどの言語用のライブラリがあり、それらは標準ライブラリに組み込まれていることです。そしてこれらのライブラリは、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
私はこれが最高の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]))$
これは有効な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])$'
/^(?:[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])?$/
localhostжеесть
"^((\\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])$"
新しいネットワークフレームワークはstruct IPv4Addressとstruct IPv6Addressのための無効な初期化子を持っています。これらはIPアドレス部分を非常に簡単に扱います。正規表現を使ってIPv6でこれを行うのは、すべての短縮規則では困難です。
あいにく、私はhostnameに対する優雅な答えを持っていません。
ネットワークフレームワークは最近のものなので、最近の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"
私はこれがIPアドレスに対してかなりうまくいくことがわかりました。それはトップの答えのように検証しますが、それはまたipが隔離されていることを確認しますので、テキストやそれ以上の数字/小数はipの前後にありません。
(?<!\ S)(?:(?:\ d | [1-9]\d | 1\d\d | 2 [0-4]\d | 25 [0-5])\ b |。\b){7}(?!\ S)
>>> 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
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:]]|$)'
ここで残念なのは、オクテットを検証する正規表現部分が、提供されている多くの解決策でそうであるように繰り返されるという事実です。これはパターンのインスタンスよりも優れていますが、使用されている正規表現でサブルーチンがサポートされている場合は、繰り返しを完全に排除できます。次の例では、grep
の-P
スイッチを使用してこれらの関数を有効にし、先読み機能と後書き機能も利用します。 (私が選択した関数名はオクテットのための 'o'です。私は名前として 'octet'を使うことができましたが、簡潔にしたいと思いました。)
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))'
これはAntでANT_OPTSからプロキシホストIPまたはホスト名を取得するために使用した正規表現です。これはプロキシIPを取得するために使用されたため、フォークされたJVM用にプロキシを設定する前にAntの「到達可能」テストを実行できました。
^.*-Dhttp\.proxyHost=(\w{1,}\.\w{1,}\.\w{1,}\.*\w{0,})\s.*$
これを試して:
((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
私の場合はうまくいきます。
AddressRegex = "^(ftp|http|https):\/\/([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5})$";
HostnameRegex = /^(ftp|http|https):\/\/([a-z0-9]+\.)?[a-z0-9][a-z0-9-]*((\.[a-z]{2,6})|(\.[a-z]{2,6})(\.[a-z]{2,6}))$/i
これはこの型の検証にのみ使用されます。
がhttp://www.kk.comの場合にのみ機能)http://www.kk.co.in
はには機能しません