gpt4 book ai didi

regex - 如何匹配正则表达式中的数值?

转载 作者:行者123 更新时间:2023-12-02 00:39:04 24 4
gpt4 key购买 nike

好吧,这是我自己遇到的一个非常有趣的挑战。

我的正则表达式采用如下输入行:

147.63.23.156/15994.182.23.55/56134.56.33.11/12

I need it to output a regular expression that matches the range represented. Let me explain.

For example, if the RegEx receives 147.63.23.156/159, then it needs to output a RegEx that matches the following:

147.63.23.156147.63.23.157147.63.23.158147.63.23.159

How can I do this?

Currently I have:

(\d{1,3}\.\d{1,3}\.\d{1,3}\.)(\d{1,3})/(\d{1,3})
  • $1 包含第一个 xxx.xxx.xxx. 部分
  • $2 包含数字的下限
  • $3 包含数字的上限

最佳答案

正则表达式确实不是验证 IP 地址的好方法,我想在前面说明这一点。解析地址并做一些简单的算术比较它们要容易得多。几个小于大于,你就在那里。

也就是说,编写正则表达式生成器似乎是一项有趣的练习。我想出了一大堆 Python 代码来生成这些正则表达式。在我展示代码之前,这是它为几个 IP 范围生成的正则表达式示例:

1.2.3.4 to 1.2.3.4              1\.2\.3\.4
147.63.23.156 to 147.63.23.159 147\.63\.23\.15[6-9]
10.7.7.10 to 10.7.7.88 10\.7\.7\.([1-7]\d|8[0-8])
127.0.0.0 to 127.0.1.255 127\.0\.[0-1]\.(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))

我将分两部分展示代码。首先,为简单整数范围生成正则表达式的部分。其次,处理完整 IP 地址的部分。

匹配号码范围

第一步是弄清楚如何生成匹配任意整数范围(例如 12-28 或 0-255)的正则表达式。下面是我的实现中出现的正则表达式示例:

156 to 159   15[6-9]
1 to 100 [1-9]|[1-9]\d|100
0 to 255 \d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5])

现在是代码。有许多内联评论解释了其背后的逻辑。总的来说,它依赖于大量递归和特殊大小写来尝试保持正则表达式精简。

import sys, re

def range_regex(lower, upper):
lower, upper = str(lower), str(upper)

# Different lengths, for instance 1-100. Combine regex(1-9) and
# regex(10-100).
if len(lower) != len(upper):
return '%s|%s' % (
range_regex(lower, '9' * len(lower)),
range_regex(10 ** (len(lower)), upper)
)

ll, lr = lower[0], lower[1:]
ul, ur = upper[0], upper[1:]

# One digit numbers.
if lr == '':
if ll == '0' and ul == '9':
return '\\d'
else:
return '[%s-%s]' % (ll, ul)

# Same first digit, for instance 12-14. Concatenate "1" and regex(2-4).
elif ll == ul:
return ll + sub_range_regex(lr, ur)

# All zeros to all nines, for instance 100-399. Concatenate regex(1-3)
# and the appropriate number of \d's.
elif lr == '0' * len(lr) and ur == '9' * len(ur):
return range_regex(ll, ul) + '\\d' * len(lr)

# All zeros on left, for instance 200-649. Combine regex(200-599) and
# regex(600-649).
elif lr == '0' * len(lr):
return '%s|%s' % (
range_regex(lower, str(int(ul[0]) - 1) + '9' * len(ur)),
range_regex(ul + '0' * len(ur), upper)
)

# All nines on right, for instance 167-499. Combine regex(167-199) and
# regex(200-499).
elif ur == '9' * len(ur):
return '%s|%s' % (
range_regex(lower, ll + '9' * len(lr)),
range_regex(str(int(ll[0]) + 1) + '0' * len(lr), upper)
)

# First digits are one apart, for instance 12-24. Combine regex(12-19)
# and regex(20-24).
elif ord(ul[0]) - ord(ll[0]) == 1:
return '%s%s|%s%s' % (
ll, sub_range_regex(lr, '9' * len(lr)),
ul, sub_range_regex('0' * len(ur), ur)
)

# Far apart, uneven numbers, for instance 15-73. Combine regex(15-19),
# regex(20-69), and regex(70-73).
else:
return '%s|%s|%s' % (
range_regex(lower, ll + '9' * len(lr)),
range_regex(str(int(ll[0]) + 1) + '0' * len(lr),
str(int(ul[0]) - 1) + '9' * len(ur)),
range_regex(ul + '0' * len(ur), upper)
)

# Helper function which adds parentheses when needed to sub-regexes.
# Sub-regexes need parentheses if they have pipes that aren't already
# contained within parentheses. For example, "6|8" needs parentheses
# but "1(6|8)" doesn't.
def sub_range_regex(lower, upper):
orig_regex = range_regex(lower, upper)
old_regex = orig_regex

while True:
new_regex = re.sub(r'\([^()]*\)', '', old_regex)

if new_regex == old_regex:
break
else:
old_regex = new_regex
continue

if '|' in new_regex:
return '(' + orig_regex + ')'
else:
return orig_regex

匹配的IP地址范围

有了这个功能,我随后编写了一个非常相似的 IP 范围函数来处理完整的 IP 地址。代码与上面的代码非常相似,只是我们使用的是 256 进制而不是 10 进制,并且代码抛出列表而不是字符串。

import sys, re, socket

def ip_range_regex(lower, upper):
lower = [ord(c) for c in socket.inet_aton(lower)]
upper = [ord(c) for c in socket.inet_aton(upper)]

return ip_array_regex(lower, upper)

def ip_array_regex(lower, upper):
# One octet left.
if len(lower) == 1:
return range_regex(lower[0], upper[0])

# Same first octet.
if lower[0] == upper[0]:
return '%s\.%s' % (lower[0], sub_regex(ip_array_regex(lower[1:], upper[1:])))

# Full subnet.
elif lower[1:] == [0] * len(lower[1:]) and upper[1:] == [255] * len(upper[1:]):
return '%s\.%s' % (
range_regex(lower[0], upper[0]),
sub_regex(ip_array_regex(lower[1:], upper[1:]))
)

# Partial lower subnet.
elif lower[1:] == [0] * len(lower[1:]):
return '%s|%s' % (
ip_array_regex(lower, [upper[0] - 1] + [255] * len(upper[1:])),
ip_array_regex([upper[0]] + [0] * len(upper[1:]), upper)
)

# Partial upper subnet.
elif upper[1:] == [255] * len(upper[1:]):
return '%s|%s' % (
ip_array_regex(lower, [lower[0]] + [255] * len(lower[1:])),
ip_array_regex([lower[0] + 1] + [0] * len(lower[1:]), upper)
)

# First octets just 1 apart.
elif upper[0] - lower[0] == 1:
return '%s|%s' % (
ip_array_regex(lower, [lower[0]] + [255] * len(lower[1:])),
ip_array_regex([upper[0]] + [0] * len(upper[1:]), upper)
)

# First octets more than 1 apart.
else:
return '%s|%s|%s' % (
ip_array_regex(lower, [lower[0]] + [255] * len(lower[1:])),
ip_array_regex([lower[0] + 1] + [0] * len(lower[1:]),
[upper[0] - 1] + [255] * len(upper[1:])),
ip_array_regex([upper[0]] + [0] * len(upper[1:]), upper)
)

关于regex - 如何匹配正则表达式中的数值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3411249/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com