質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

4回答

6341閲覧

Python3 正規表現を用いてIPアドレスを判定したい

yuyu127

総合スコア27

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

1グッド

2クリップ

投稿2017/11/23 07:36

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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
  1. 空だったらダメ
  2. ドットで区切って四つじゃなかったらダメ
  3. 範囲外だったらダメ

追記

正規表現を使っていないのに、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
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuyu127

2017/11/23 08:00

LouiS0616様 ご回答ありがとうございます。 正しい結果は出るようになりました。 ですが、正規表現でなんとかしたいと思っております。
wakame

2017/11/23 08:06

横からですが正規表現にこだわる理由が知りたいと思いました。
LouiS0616

2017/11/23 08:07

ちょうどsuyamaさんが正規表現による回答を書いてくださったので、そちらをご覧ください。
LouiS0616

2017/11/23 08:16

ちょっと気になって本家の実装を見てみました。 思ったよりゴリゴリ書いていて面白かったので、やっぱり回答にはなっていませんが追記しておきました。
yuyu127

2017/11/23 23:08

wakame様 お世話になっております。 正規表現を勉強しており、せっかくなら正規表現で解決したいと思った次第です。
LouiS0616

2017/11/27 04:20

外した回答でBAいただいてしまったので、ちょっと追記しました。 正規表現に苦手意識がある(というか体系的に学んでいない)ので間違ったこと書いていないかちょっと不安だったりします。
yuyu127

2017/11/27 13:30

LouiS0616さん ありがとうございます。 詳細に教えていただき、関数まで作っていただいたのでBAとさせていただきました。 正規表現の場合、$で行末を指定することでできました。
guest

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

YouheiSakurai

総合スコア6142

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuyu127

2017/11/27 03:10

YouheiSakuraiさん ご回答ありがとうございました。解決できそうです。 コード内容を詳しく拝見させていただきます。
guest

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuyu127

2017/11/27 03:05

suyamaさん ありがとうございました。本URLを参考にさせていただきます。
退会済みユーザー

退会済みユーザー

2017/11/27 03:12

すぐ手元に本がないのでうろ覚えですが、正規表現ハンドブックという本に色々なパターンにマッチさせるための正規表現が収録されていたと思います。ご参考までに。 http://www.sbcr.jp/products/4797328509.html
yuyu127

2017/11/27 13:33

suyamaさん 情報ありがとうございます。 参考にさせていただきます。
guest

0

RFC3986

RFC3986 では ABNF 形式で IPv4address 書式を定義しているので、参考にすると良いと思います。

昔、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
think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuyu127

2017/11/27 03:04

think49さん ご回答ありがとうございました。 正規表現を勉強していて出てきた課題でしたが、IPv6も考えてみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問