2

当我完成 regex101 测验/课程时,我应该匹配一个 IP 地址(没有前导零)。

现在以下

^[^0]+[0-9]+\\.[^0]+[0-9]+\\.[^0]+[0-9]+\\.[^0]+[0-9]+$

火柴23.34.7433.33

但无法匹配 1.2.3.4 等单个数字

为什么会这样,当我+的应该匹配“1 到无限”次时......?

4

6 回答 6

3

实际上,您为 IP 地址中的每个数字匹配超过 2 位数字,因为您有:

[^0]+[0-9]+

[^0]+至少匹配一个字符,并且[0-9]+至少匹配一个字符。两者都将匹配“至少 2 个字符”(字符在字符类的范围内)。

由于我上面提到的原因,也23.34.7433.3 与您的正则表达式不匹配。

您可能会出于您所说的目的尝试此正则表达式:

^(?:[1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}$

[1-9][0-9]{0,2}将匹配最多 3 位数字,不带前导0.

编辑:您在评论中提到0.0.0.0(个位零)也将被接受。上面修改后的正则表达式将是:

^(?:(?:[1-9][0-9]{0,2}|0)\.){3}(?:[1-9][0-9]{0,2}|0)$
于 2013-09-06T20:29:39.397 回答
2

[0-9]+应该[0-9]*

  • *匹配 0 个或更多。
  • +匹配 1 个或多个。

您已经有了案例[^0]<--- 这实际上是错误的,因为它也会匹配字母。

除此之外,它将匹配第一个不为零的字符,然后匹配至少一个数字。

它应该写成

 [1-9][0-9]*

这基本上检查第一个字母并查看它是否是一个介于 1-9 之间的数字,然后接下来的数字(0 nums 到无限 nums)是一个数字 0-9。

然后这个就出来了。

^[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*$

正则表达式可视化

在 Debuggex 上实时编辑

清理它。

^(?:[1-9][0-9]*\.){3}[1-9][0-9]*$

这应该工作......

^(?:[1-9][0-9]*\.|[0-9])(?:[1-9][0-9]*\.|[0-9])(?:[1-9][0-9]*\.|[0-9])(?:[1-9][0-9]*|[0-9])$

清理干净。

^(?:(?:[1-9][0-9]*|0)\.){3}(?:[1-9][0-9]*|0)$
于 2013-09-06T20:33:22.250 回答
2

假设您要检查 IPv4,我建议您使用以下模式:

^(?<nb>2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9])(?>\.\g<nb>){3}$

我已经定义了一个命名的子模式nb以使模式更短,但是如果您愿意,可以重写所有并替换\g<nb>

^(?>2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9])(?>\.(?>2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9])){3}$

不允许使用大于 255 的数字。

图案细节:

目标是描述允许的内容:

  1. 以“2”开头的 3 位数字后跟 [0-4] 中的数字和 [0-9] 中的数字或 5 和 [0-5] 中的数字,因为它可以超过 255。
  2. 以“1”开头的 3 位数字后面可以跟任意两位数字。
  3. 任何不以“0”开头的两位数
  4. 任何 1 位数字(包括零)

如果我将这些规则一一添加,我将获得

  1. 2(?>[0-4][0-9]|5[0-5])
  2. 2(?>[0-4][0-9]|5[0-5]) | 1[0-9]{2}
  3. 2(?>[0-4][0-9]|5[0-5]) | 1[0-9]{2} | [1-9][0-9]
  4. 2(?>[0-4][0-9]|5[0-5]) | 1[0-9]{2} | [1-9][0-9] | [0-9]

现在我有一个允许数字的定义。我可以减少一点模式的大小替换
[1-9][0-9] | [0-9][1-9]?[0-9]

然后你只需要添加点重复子模式四次:xxxx

但由于只有三个点,我写了第一个数字,然后重复 3 次包含一个点和一个数字的组:

2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9]  # the first number
(?>\.2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9]){3} # the group repeated 3 times

为了确保字符串不包含我所描述的 IP 的任何其他内容,我为字符串的开头和字符串 ^的结尾添加了锚点$,然后字符串以 IP 开头和结尾。

要减小模式的大小,您可以定义一个命名组,该组允许重用它包含的子模式,

然后你可以像这样重写模式:

^
(?<nb> 2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9] )  # named group definition
(?> \. \g<nb> ){3} # \g<nb> is the reference to the subpattern named nb
$
于 2013-09-06T21:30:40.837 回答
1

您的正则表达式将匹配ABCDEFG999.FOOBSR888等,因为[^0]是除零以外的任何字符,并且+.

我想你想要这个:

^[1-9]\d*(\\.[1-9]\d*){3}$

用它们的等价物替换了各种冗长的表达式,这是 4 组数字,每组都以非零开头。

实际上问题要复杂得多,因为您的方法(一旦更正)允许999.999.999.999,这不是有效的IP。

于 2013-09-06T20:36:28.757 回答
0

要匹配 IP 地址,您应该使用以下模式: \b(?:\d{1,3}.){3}\d{1,3}\b

取自这里: http ://www.regular-expressions.info/examples.html

于 2013-09-06T20:39:54.127 回答
0

这可能是因为您需要在两个点“。”之间至少有两个数字。

尝试使用这种模式:^[^0]+[0-9]*\.[^0]+[0-9]*\.[^0]+[0-9]*\.[^0]+[0-9]*$

于 2013-09-06T20:30:35.243 回答