регулярное выражение для сопоставления IP с маской в ​​jsonschema - PullRequest
0 голосов
/ 08 ноября 2018

Есть хорошее решение здесь для сопоставления 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), но, похоже, содержит что-то незаконное.Не могу понять, что это такое, посмотрел , , , , , , а также попытался использовать 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?

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

Вы не поверите, но двух обратных косых черт было недостаточно!

Он не работает с 2-мя обратными слешами, ему нужно 3 или 4, поэтому он пойдет с 3. Нет необходимости давать ему больше, чем нужно.

Пришлось потратить еще несколько часов, чтобы понять это, но нашел этот ответ от @TimPietzcker, который говорит:

Вам нужно использовать escape-слэши для регулярных выражений, а затем бежать их снова для строкового процессора

Итак рабочий код выглядит следующим образом (слегка подправил исходную схему):

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
0 голосов
/ 09 ноября 2018

Для 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-адреса, а не просто полное совпадение, то вот регулярное выражение , основанное на этом . Я включил соответствие для дополнительной маски подсети:

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

(удалите разрывы строк, которые я добавил для удобства чтения). Демонстрация здесь . Должны совпадать только первые 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]))?$
...