【问题标题】:Confusion with regex expression for valid IPv4 addresses [duplicate]与有效 IPv4 地址的正则表达式混淆 [重复]
【发布时间】:2020-12-05 11:04:01
【问题描述】:

我正在尝试编写一个正则表达式,用于从包含许多有效、无效(两种)地址类型的文件中选择有效的 IPv4 地址。 我已经为此编写了正则表达式,但仍然打印出两个无效的 IPv4 地址 - 255.255.256.255 和 8.234.88,55 谁能帮我理解为什么这两个用我放的正则表达式打印出来。

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

我正在使用此正则表达式通过包含以下列出的 IPv4 地址的文件过滤有效的 IPv4 地址。

12.12.12.12
127.0.0.0
255.255.256.255
344.19.0.1.
12.255.12.255
138.168.5.193
256.123.256.123
195.45.13.0
8.234.88.55
1334.0.1.234
196.83.83.191
133.133.133.133
8.234.88,55
203.26.27.38
88.173.71.66
136.186.20.9
241.92.88.103

我想知道为什么这个正则表达式匹配 255.255.256.255 和 8.234.88,55 IPv4 地址。

【问题讨论】:

  • 请勿发布链接或截图。相反,请发布minimal reproducible example
  • Please don't post images of text。这里的人认为这是邪恶的。
  • 我已按照建议进行了更改。谢谢
  • why this regex expression is matching with 255.255.256.255 and 8.234.88,55 IPv4 addresses 它没有。您检查正则表达式是否匹配的方法有缺陷。
  • 搜索regex for IPV4 addresses时还有200多个其他Q/A。这就是维护一个包含常见问题及其答案的数据库的目的 ;-) ... 但是,很高兴您在下面得到了一些好的反馈。祝你好运。

标签: linux grep


【解决方案1】:

((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.)

我已经在 C++ 中尝试过您的表达方式。 在此处解决逗号问题的点之前添加一个额外的斜线。

它解析了一个逗号,因为你缺少一个斜杠,它的编写方式将点解释为“解析除 EOL 之外的任何字符”。

当您输入 [01] 时,您的表达式还允许值以 0 为前缀吗?

有一个关于如何处理表达式的建议:如果它只有一个数字,它怎么写?然后是 2 位数,然后是 3...

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

【讨论】:

  • 您将regex 要求的\ 转义与将字符串作为源代码编写的C++ 规则要求的转义混淆了。您必须在 C++ 源代码中使用双 \,但实际上,字符串中只有一个 \。另一个是语言要求的。原来的正则表达式在这一点上是正确的。如果用撇号包裹,则问题中提供的regex 可以在命令行中按原样使用,无需额外转义。
【解决方案2】:

您的正则表达式未锚定到字符串的开头和结尾。它匹配每一行的片段,而不是整行。

将您的regex 放在^$ 之间。

^ 匹配字符串的开头; $ 匹配字符串的结尾。

如果启用多行匹配,^ 匹配行首,$ 匹配行尾。

另外,regex 稍微不正确,这使得它的匹配程度低于应有的程度。 IPv4 地址总是有 4 个组成部分。由于{1,3},您的regex 允许2 到4 个组件。结合缺少锚点,它会在您提到的行中找到两个匹配项。

看看regex101.com

regex 应该是:

^((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]?)$

【讨论】:

    【解决方案3】:

    为什么这个正则表达式匹配 255.255.256.255 和 8.234.88,55 IPv4 地址。

    它没有。它匹配该字符串的部分内容。你很可能做到了:

    $ echo '255.255.256.255' | grep -E '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){1,3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
    255.255.256.255
    

    是的,它有效。但是该模式与整体不匹配,它分别匹配部分255.255.256.255{1,3} 允许第一部分只匹配一次或两次,不一定是 3 次。喜欢:

     ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.)((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.)(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
       25  5                                 .   25  5                                 .                             2    5    6.255
                                                                                                                               ^^^^^ - left over
    

    由于{1,3},第一部分只能匹配一次。因为grep 将正则表达式应用于字符串的一部分,并且因为完整的正则表达式匹配,所以该行被打印。

    对于8.234.88,558.234.88 部分匹配,,55 不匹配。很酷:

    $ echo '8.234.88,55' | grep --color -E '(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){1,3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){1}'
    8.234.88,55
    ^^^^^^^^ - is red
    

    要匹配整行,请执行grep -x 或添加锚点^....$,或者很可能您想将{1,3} 更改为{3} 以精确匹配3 个部分。

    【讨论】:

      猜你喜欢
      • 2018-06-01
      • 2018-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-06
      • 1970-01-01
      • 1970-01-01
      • 2011-07-14
      相关资源
      最近更新 更多