【问题标题】:regex to match IP with mask in a jsonschema正则表达式将 IP 与 jsonschema 中的掩码匹配
【发布时间】:2019-04-12 05:12:30
【问题描述】:

有一个很好的解决方案here 可以匹配带有掩码的IP,例如192.168.0.1/24。我添加了来自https://regex101.com/ 的建议来转义斜线,它看起来像这样:

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

这似乎确实适用于 regex101。

它需要存在于一个 json 文件(jsonschema 文件)中,但似乎包含一些非法的东西。无法弄清楚它是什么,查看了thisthisthis,还尝试按照here 的建议使用 ujson 而不是 json(在 python 中),但没有任何效果。

以下包含该正则表达式的 jsonschema:

{
    "comment": "ipv4 with a mask",
    "data": {
        "network": {
        }
    },
    "schema": {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "title": "ipv4 with a mask",
        "type": "object",
        "properties": {
            "subnet": {
                "title": "subnet",
                "type": "string",
                "pattern": "((^|\.)((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]?\d))){4}\/(?:\d|[12]\d|3[01])$"
            }
        }
    }
}

...不幸的是甚至不会解析。 Python 在说:

JSONDecodeError: Invalid \escape: line 16 column 33 (char 380)

我一直在使用库 fastjsonschema 来检查这些东西,但甚至无法解析 json 并获得那么远。

有谁知道如何解决这个问题,以某种方式让那段正则表达式在 jsonschema 中起作用?

【问题讨论】:

  • Json 不喜欢反斜杠,所以你必须将它们转义 ((^|\\.)((25[0-5])|(2[0-4]\\d)|(1\\d\\d)|([1-9]?\\d))){4}\\\/(?:\\d|[12]\\d|3[01])$ 使用像 jsonschemavalidator.net 这样的网站来检查你的架构
  • @TomPowis 我只是将您的字符串放入 json 中,但 python 中的解析器仍然不满意。 @IvanGodko 今天早些时候正在查看它,但相信它会验证 192.168.0.1 而不是 192.168.0.1/24
  • 也许将其保存为原始字符串? r"..."那当然不用转义了
  • @TomPowis 在您的 JSON 转义正则表达式字符串中,{4} 之后有一个额外的反斜杠。

标签: python json regex jsonschema


【解决方案1】:

对于 JSON,您需要将每个反斜杠 \ 转义为另一个反斜杠:

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

所以在 JSON 模式中,它看起来像:

"pattern": "((^|\\.)((25[0-5])|(2[0-4]\\d)|(1\\d\\d)|([1-9]?\\d))){4}\\/(?:\\d|[12]\\d|3[01])$"

您找到的正则表达式(在链接中)无论如何都与数字分组不匹配。用几个例子试试 - 完全匹配是正确的,但返回的包括带数字的点或只是点。

如果您想要 IP 地址的所有部分而不是完全匹配,那么这里有一个正则表达式 based on this one。我已经包含了一个可选子网掩码的匹配:

^(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[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
(?:\/(\d|[12]\d|3[01]))?$

(删除我为便于阅读而添加的换行符。)Demo here。只有前 3 个地址应该匹配,而不是其余的。

如果你只想要完整的匹配,而不是单个部分,那么使用这个:

^(?:(?: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]?)
(?:\/(?:\d|[12]\d|3[01]))?$

【讨论】:

    【解决方案2】:

    您不会相信,但 2 个反斜杠还不够!

    它不能与 2 个反斜杠一起使用,它需要 3 或 4,所以将与 3 一起使用。不需要给它比它需要的更多。

    不得不再花几个小时来实现这一点,但从@TimPietzcker 找到了this answer,上面写着:

    您需要对正则表达式使用反斜杠转义,然后转义 它们再次用于字符串处理器

    所以工作代码看起来像这样(稍微调整了原始模式):

    import json    
    import fastjsonschema
    
    schema = '''{
        "data": [{"subnet": "192.168.1.1/24"}],
            "$schema": "http://json-schema.org/draft-04/schema#",
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "subnet": {
                        "title": "subnet",
                        "type": "string",
                        "pattern": "((^|\\\.)((25[0-5])|(2[0-4]\\\d)|(1\\\d\\\d)|([1-9]?\\\d))){4}\\\/(?:\\\d|[12]\\\d|3[01])$"
                    }
                }
            }
        }''' 
    
    schema = json.loads(schema)
    validate = fastjsonschema.compile(schema)
    
    def check_subnets(testcase):
        try: 
            validate([{"subnet": testcase}])
            print("yes a subnet")
        except fastjsonschema.JsonSchemaException:
            print("not a subnet")    
    

    然后进行一些测试:

    >>> check_subnets("192.168.0.1/24") 
    yes a subnet
    >>> check_subnets("192.168.0.1/50")
    not a subnet
    >>> check_subnets("192.168.0.1")
    not a subnet
    >>> check_subnets("192.168.0.900/24")
    not a subnet
    

    【讨论】:

    • Wrt "您需要对正则表达式使用转义反斜杠,然后为字符串处理器再次转义它们":那是因为您将 JSON 字符串放入 Python然后加载它。如果它位于单独的 JSON/文本文件中 - “它需要存在于 json 文件(jsonschema 文件)中” 根据您的问题 - 每个正则表达式不需要超过 1 个额外的反斜杠 -反斜杠。这就是使用r'some str' 将其设置为“原始”字符串的地方。仍然认为每个正则表达式反斜杠需要 3 个 extra 反斜杠,因此总共需要 4 个。有趣的是,它与 3 一起使用。+1 用于跟进。
    • 好吧,你对这种东西有耐心,这是最近不得不处理的最不愉快的问题之一。r'some str' 运气不好,肯定会直接看数字如果这是从文件加载一次,如果投入生产,或者如果它开始抱怨再次转义,则使用反斜杠。
    猜你喜欢
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 2022-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多