用逗号正则表达式分隔的IPv4地址列表?

时间:2020-03-25 18:41:30

标签: regex

我有一个正则表达式来匹配IPv4地址:

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

现在我想要相同的正则表达式,但是要使用逗号分隔的IPv4地址列表

示例(不能用逗号结尾字符串):

172.24.64.100.0,172.25.64.100.0,172.26.64.100 

我该怎么做?

谢谢

1 个答案:

答案 0 :(得分:0)

如果该语言支持PCRE(PHP)引擎,则可以使用以下正则表达式。请注意,它使用子例程。

(?=(25[0-5]|2[1-4]\d|1\d{2}|[1-9]\d|[1-9])){0}(?=((?1)(?:\.(?1)){3})){0}(?=(?2)(?:,(?2))*$)(?2)

Demo

正则表达式执行以下操作。

定义捕获组1

(?=           # begin positive lookahead
  (           # begin capture group 1
    25[0-5]   # match 250-255
    |         # or
    2[0-4]\d  # match 200-249
    |         # or
    1\d{2}    # match 100-199
    |         # or
    [1-9]\d   # match 10-99
    |         # or
    [1-9]     # match 1-9
  )           # end capture group 1
)             # end positive lookahead
{0}           # execute postive lookahead zero times

定义捕获组2

(?=           # begin positive lookahead
  (           # begin cap grp 2
    (?1)      # execute cap grp 1 instructions
    (?:       # begin non-cap grp
      \.(?1)  # match '.' then execute cap grp 1 instructions
    {3}       # end non-cap grp   
  )           # end cap grp 2
)             # end positive lookahead
{0}           # execute postive lookahead zero times

确认字符串仅包含逗号分隔的有效IPv4地址

(?=           # begin positive lookahead
  (?2)        # execute cap grp 2 instructions
  (?:         # begin non-cap grp 
    ,(?2)     # match ',' then execute cap grp 2 instructions 
  )           # end non-cap grp
  *           # execute non-cap grp 0+ times
  $           # match end of line
)             # end positive lookahead

匹配IPv4地址

(?2)          # execute cap grp 2 instructions

某些支持子例程(或 subexpressions )的正则表达式引擎可能具有不同的语法。例如,Ruby使用\g<1>而不是(?1)。可以选择使用命名的捕获组。 PCRE将(?P>sue)用于名为“ sue”的捕获组。有关详细信息,请参见this discussion

如果不希望使用子例程,或者该语言的正则表达式引擎不支持子例程(我理解,Python是其中之一),则可以用捕获组1的内容替换(?1),例如:< / p>

25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|[1-9]

自然,正则表达式的大小会大大增加(考虑替换(?2))。使用子例程的另一个优点是每个子例程可以单独进行测试。

非正则表达式方法

我认为开发上述正则表达式是一种练习(也是向某些读者介绍正则表达式子例程的机会),但是我不建议使用这种方法来支持普通语言工具的使用。例如,在Ruby中,仅需要几行代码,如下所示。那些不熟悉Ruby的人应该能够了解代码中正在发生的事情。

require 'ipaddr'

def ipv4s(str)
  str.split(',').map do |s|
    i = IPAddr.new(s)
    raise ArgumentError, "'#{s}' is not an IP address" if i.nil?
    raise ArgumentError, "'#{s}' is not an IPv4 address" unless i.ipv4?
    s
  end
end

ipv4s("172.24.64.100,172.25.64.100,172.26.64.100")
  #=> "2001:0DB8:AC10:FE01:0000:0000:0000:0000"
ipv4s("172.24.64.100, 172.25.64.100,172.26.64.100")
  #=> IPAddr::InvalidAddressError ( 172.25.64.100)
                                   ^
ipv4s("172.2403.64.100,172.25.64.100,172.26.64.100")
  #=> IPAddr::InvalidAddressError (72.2403.64.100)
                                      ^^^^
ipv4s("cat 172.24.64.100,172.25.64.100,172.26.64.100")
  #=> IPAddr::InvalidAddressError (cat 172.24.64.100)
                                   ^^^^ 
ipv4s("172.24.64.100,172.25.64.275,172.26.64.100")
  #=> IPAddr::InvalidAddressError (172.25.64.275)
                                             ^^^