从Hive SQL的一个正则表达式说起


=Start=

缘由:

目标,用Hive SQL的正则表达式匹配出IPv4中 172 段的私有IP地址(172.16.0.0/12 即 172.16.0.0到172.31.255.255)

错误1:一开始想直接用 [16-31] 来匹配 16,17,…,30,31 这一区间的数字,但是正则匹配是以单个字符为单位进行的,而这里的数字是是两位数,无法直接用一个字符匹配两个数字
错误2:6比3要大,因此在它们之间的【-】需要转义,否则会报语法错误
错误3:转义之后,这个正则能匹配的数字只有 1,3,6 (还有一个字符【-】)

下面整理一下和生成式AI对话的内容,方便后面参考。

正文:

参考解答:

先造一些数据用来测试

with t1 as (
select '172.' as ip_head, '.1.2' as ip_tail
)
, t2 as (
select
idx, concat(ip_head,idx,ip_tail) as ip1
from t1
lateral view posexplode(split(space(40),' ')) pi as idx, empty
)

SELECT
*
-- ,ip1 not rlike '^172\.[16-31]\.'
,ip1 rlike '^172\\.[16\\-31]\\.' --不符合预期(1,3,6),且如果不对-做双斜线转义,会报错,提示正则语法错误
,ip1 rlike '^172\\.[16-78]\\.' --不符合预期(1,6,7,8),但因为7比6要大,所以不对-做双斜线转义也不会提示正则语法错误
,ip1 rlike '^172\\.(1[6-9]|2[0-9]|3[01])\\.' --符合预期
FROM
t2

question
Hive SQL中正则表达式 '^172\\.[16\\-31]\\.' 可以匹配的内容是什么样的?

answer
在Hive SQL中,正则表达式 '^172\\.[16\\-31]\\.' 并不能正确地匹配你所期望的IPv4地址范围(即172.16.0.0到172.31.255.255)。这个正则表达式存在几个问题:

  1. 字符类中的范围使用错误:在正则表达式中,[16\\-31] 并不能正确地表示16到31之间的数字。正确的表示应该是使用 - 来定义一个范围,例如 [16-31]
  2. 点号 . 的匹配:在正则表达式中,. 是一个特殊字符,代表任何单个字符。为了匹配字面意义的点号 ., 应该使用转义字符 \.
  3. 范围不完整:此正则表达式仅匹配了IPv4地址的前两部分,而没有考虑到后续部分。

正确的正则表达式

为了匹配172.16.0.0到172.31.255.255范围内的IPv4地址,应该使用如下正则表达式:

^172\.(1[6-9]|2[0-9]|3[01])\.(?:[0-9]{1,3})\.(?:[1-9][0-9]?|1[0-9]{2}|2[0-4][0-9]|25[0-5])$

解释:

  • ^172\.:匹配以 “172.” 开头的字符串。
  • (1[6-9]|2[0-9]|3[01]):匹配第二部分,范围是 16 到 31。
  • (?:[0-9]{1,3}):匹配第三部分,范围是 0 到 255。
  • (?:[1-9][0-9]?|1[0-9]{2}|2[0-4][0-9]|25[0-5]):匹配第四部分,范围是 1 到 255。
  • $:表示字符串的结束。

Hive SQL 示例

使用 RLIKE 函数来筛选符合条件的IPv4地址:

SELECT ip_address
FROM your_table
WHERE ip_address RLIKE '^172\\.(1[6-9]|2[0-9]|3[01])\\.(?:[0-9]{1,3})\\.(?:[1-9][0-9]?|1[0-9]{2}|2[0-4][0-9]|25[0-5])$';

注意事项

  • 在 Hive 中,正则表达式中的反斜杠 \ 需要转义,因此使用的是 \\
  • 如果你的表中有多个字段需要检查,可以对每个字段分别应用上述条件。
  • 如果表中有大量的数据,使用 RLIKE 可能会影响性能,尤其是在大数据集上。

通过上述方法,你可以准确地筛选出位于指定范围内的IPv4地址。如果需要处理更复杂的条件或大规模数据集,可能需要考虑使用其他工具或方法来提高效率。

参考链接:

通义千问
https://tongyi.aliyun.com/qianwen/

正则表达式区间 上的”-“ 横线未转义引发的两个问题
https://blog.csdn.net/janet1100/article/details/104532136

=END=


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注