PythonでIPアドレスを正規表現でマッチさせようとしましたが、
すべてFalseとなってしまいます。
下記の場合、Trueとしたいのですが、Falseとなります。
解決方法はありますでしょうか。
Python3
1address = "1.2.3.4" 2 3m = re.match('^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3} ([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/', address) 4 5if m: 6 print("Ture") 7else: 8 print("False")
よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
ベストアンサー
註:以下の回答は、正規表現に関するものではありません。
何らかの制約や目標があって正規表現を用いたいなら、あまり参考にはならないと思います。
IPアドレスに関する標準ライブラリを利用するのが良いと思います。
Python
1>>> import ipaddress 2>>> 3>>> ipaddress.ip_address('1.2.3.4') 4IPv4Address('1.2.3.4') 5>>> 6>>> ipaddress.ip_address('1.2.3.300') 7Traceback (most recent call last): 8 File "<stdin>", line 1, in <module> 9 File "C:\ProgramData\Miniconda3\lib\ipaddress.py", line 54, in ip_address 10 address) 11ValueError: '1.2.3.300' does not appear to be an IPv4 or IPv6 address
こういう関数を作ってもいいかもしれませんね。
Python
1import ipaddress 2 3def is_valid_ip(arg): 4 try: 5 ipaddress.ip_address(arg) 6 return True 7 except ValueError: 8 return False
参考までに
CPythonの実装を見てみると、案外ゴリゴリやってるみたいですね。
Python
1@classmethod 2def _ip_int_from_string(cls, ip_str): 3 """Turn the given IP string into an integer for comparison. 4 Args: 5 ip_str: A string, the IP ip_str. 6 Returns: 7 The IP ip_str as an integer. 8 Raises: 9 AddressValueError: if ip_str isn't a valid IPv4 Address. 10 """ 11 if not ip_str: 12 raise AddressValueError('Address cannot be empty')
octets = ip_str.split('.') if len(octets) != 4: raise AddressValueError("Expected 4 octets in %r" % ip_str)
try: return int.from_bytes(map(cls._parse_octet, octets), 'big') except ValueError as exc: raise AddressValueError("%s in %r" % (exc, ip_str)) from None
- 空だったらダメ
- ドットで区切って四つじゃなかったらダメ
- 範囲外だったらダメ
追記
正規表現を使っていないのに、BAを貰ってしまったので。
質問者様のコードは、ちょっと修正すればちゃんと動きます。
Python
1m = re.match('(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])', address)
問題のあった点
- エスケープすべきでない文字をエスケープしていた
- しかしながらそもそもre.matchなら文頭記号と文末記号は不用
- 無駄な空白が入っていた
- 文末の一文字も余計だった(文末記号以降にオプション付ける文法とかありましたっけ...?)
Python
1import re 2import random 3 4def get_random_address(): 5 return '{}.{}.{}.{}'.format( 6 *[random.randrange(255) for _ in range(4)] 7 ) 8 9compiled_pattern = re.compile('(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])') 10for _ in range(10000): 11 address = get_random_address() 12 if not compiled_pattern.match(address): 13 print('False', address) 14 15print('True')
一応上記のゴリゴリテストを通過します。
正規表現あんまり得意じゃないので、変なこと書いていたらすみません。
投稿2017/11/23 07:39
編集2017/11/27 04:18総合スコア35668
0
python
1 2from ipaddress import IPv4Address 3from itertools import repeat 4from re import compile 5from random import randint 6 7ipv4 = compile(r'.'.join(repeat( 8 r'(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])', 4))) 9 10for _ in range(100000): 11 address = str(IPv4Address(randint(0, 0xFFFFFFFF))) 12 assert ipv4.match(address), address 13 14address = "1.2.3.4" 15m = ipv4.match(address) 16if m: 17 print("Ture") 18else: 19 print("False") 20
投稿2017/11/24 16:07
総合スコア6142
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
IPv4アドレスにマッチする文字列を抽出する正規表現は下記となるようです。
text
1(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3} ([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])
IPアドレスのフォーマットチェック(正規表現) | IPラーニング
http://www.geolocation.co.jp/learn/program/07.html
IPv6アドレスの場合についても、参考までリンクします。
IPv6アドレスをより妥当な正規表現でマッチする。 - 設計と実装の狭間で。
http://d.hatena.ne.jp/taichitaichi/20110112/1294819517
投稿2017/11/23 08:04
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/11/27 03:05
退会済みユーザー
2017/11/27 03:12
2017/11/27 13:33
0
RFC3986
RFC3986 では ABNF 形式で IPv4address
書式を定義しているので、参考にすると良いと思います。
- 付録 A. URI のために収集された ABNF - Uniform Resource Identifier (URI): 一般的構文
- RFC 5234 - Augmented BNF for Syntax Specifications: ABNF (日本語訳)
昔、JavaScriptで正規表現に書き起こしたことがあります。
JavaScript
1var DIGIT = '[\u0030-\u0039]', // [0-9] 2 dec_octet = '(?:' + DIGIT + '|[\u0031-\u0039]' + DIGIT + '|1(?:' + DIGIT + '){2}|2[\u0030-\u0034]' + DIGIT + '|25[\u0030-\u0035]), 3 IPv4address = dec_octet + '\.' + dec_octet + '\.' + dec_octet + '\.' + dec_octet; 4 5console.log(IPv4address); // (?:[0-9]|[1-9][0-9]|1(?:[0-9]){2}|2[0-4][0-9]|25[0-5]).(?:[0-9]|[1-9][0-9]|1(?:[0-9]){2}|2[0-4][0-9]|25[0-5]).(?:[0-9]|[1-9][0-9]|1(?:[0-9]){2}|2[0-4][0-9]|25[0-5]).(?:[0-9]|[1-9][0-9]|1(?:[0-9]){2}|2[0-4][0-9]|25[0-5])
ところで、IPv6には対応しなくていいのでしょうか。
(githubのコードに IPv6address
のコードもあります)
Re: yuyu127 さん
投稿2017/11/26 13:17
編集2017/11/26 13:27総合スコア18189
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/11/23 08:00
2017/11/23 08:06
2017/11/23 08:07
2017/11/23 08:16
2017/11/23 23:08
2017/11/27 04:20
2017/11/27 13:30