解析文件中的多个 json 类对象

Parsing multiple json like objects in a file

我正在尝试解析 F5 对象。它具有以下结构。

Some Garbage text
ltm virtual The_Name_51244_sdfasfdasd {
    address-status yes
    enabled
    fallback-persistence none
    profiles {
        /Common/GLOBAL_PROFILE {
            context all
        }
        /Common/http {
            context all
        }
    }
    rate-class none
    rules {
        /Common/X-F-F
    }
    log-profiles none
    source-address-translation {
        pool SOME-SNAT-POOL
        type snat
    }
    source-port preserve
    vlans {
        Vlan1111
    }
    service-down-immediate-action none
    service-policy none
    source 0.0.0.0/0
}
barbage text
ltm virtual The_Object_51244 {
    address-status yes
    enabled
    fallback-persistence none
    profiles {
        /Common/GLOBAL_PROFILE {
            context all
        }
        /Common/http {
            context all
        }
    }
    rate-class none
    rules {
        /Common/X-F-F
    }
    log-profiles none
    source-address-translation {
        pool SOME-SNAT-POOL
        type snat
    }
    source-port preserve
    vlans {
        Vlan2222
    }
    service-down-immediate-action none
    service-policy none
    source 0.0.0.0/0
}
Trailing garbage text

我的正则表达式是 ((ltm virtual) ([a-zA-Z0-9_-]*) {(.|\n)*?}) https://regex101.com/r/ATJZys/1

我要捕获的是 ltm virtual 之后的名称以及大括号之间的所有内容。但是,上面的正则表达式似乎首先停止了大括号匹配。

如何扩展它以匹配到下一个父组或匹配到大括号平衡?

您可以使用

((ltm virtual) ([a-zA-Z0-9_-]*) ({(?:[^{}]++|\g<4>)*}))

参见regex demo

详情:

  • ( - 第 1 组开始
    • (ltm virtual) - 第 2 组:ltm virtual 字符串
    • - space
    • ([a-zA-Z0-9_-]*) - 第 3 组:零个或多个字母、数字、下划线或连字符(可以是 re-written 作为 [\w-]*
    • - space
    • ({(?:[^{}]++|\g<4>)*}) - 第 4 组:{,然后 {} 或第 4 组以外的一个或多个字符的零次或多次重复,并且然后是 } 字符
  • ) - 第 1 组结束。

在 Java 中,要匹配嵌套的花括号、圆括号或任何其他在特定正则表达式模式后的单个字符定界符(更准确地说是在模式末尾),您可以使用

import java.util.*;
import java.util.regex.*;

class Test
{
    public static void main (String[] args) throws java.lang.Exception
    {
        Character markStart = '{';
        Character markEnd = '}';
        Boolean includeMarkers = true;
        int offset = (includeMarkers ? -1 : 0);
        String s = "Some Garbage text\r\nltm virtual The_Name_51244_sdfasfdasd {\r\n    address-status yes\r\n    enabled\r\n    fallback-persistence none\r\n    profiles {\r\n        /Common/GLOBAL_PROFILE {\r\n            context all\r\n        }\r\n        /Common/http {\r\n            context all\r\n        }\r\n    }\r\n    rate-class none\r\n    rules {\r\n        /Common/X-F-F\r\n    }\r\n    log-profiles none\r\n    source-address-translation {\r\n        pool SOME-SNAT-POOL\r\n        type snat\r\n    }\r\n    source-port preserve\r\n    vlans {\r\n        Vlan1111\r\n    }\r\n    service-down-immediate-action none\r\n    service-policy none\r\n    source 0.0.0.0/0\r\n}\r\nbarbage text\r\nltm virtual The_Object_51244 {\r\n    address-status yes\r\n    enabled\r\n    fallback-persistence none\r\n    profiles {\r\n        /Common/GLOBAL_PROFILE {\r\n            context all\r\n        }\r\n        /Common/http {\r\n            context all\r\n        }\r\n    }\r\n    rate-class none\r\n    rules {\r\n        /Common/X-F-F\r\n    }\r\n    log-profiles none\r\n    source-address-translation {\r\n        pool SOME-SNAT-POOL\r\n        type snat\r\n    }\r\n    source-port preserve\r\n    vlans {\r\n        Vlan2222\r\n    }\r\n    service-down-immediate-action none\r\n    service-policy none\r\n    source 0.0.0.0/0\r\n}\r\nTrailing garbage text";
        Pattern patternBefore = Pattern.compile("(ltm\s+virtual)\s+([\w-]+)\s+" + Pattern.quote(markStart.toString()));
        
        Matcher m = patternBefore.matcher(s);
        while (m.find()) {
            System.out.println("Group 1: " + m.group(1));
            System.out.println("Group 2: " + m.group(2));
            String res = getBalancedSubstring(s.substring(m.end()), markStart, markEnd, includeMarkers);
            
            System.out.println("Found nested: " + res + "\n----");
            if (res == null) {
                System.out.println("No nested parens match found, this match must be failed.");
            }
            else {
                s = s.substring(m.end()+res.length() + offset);
                m.reset(s);
            }
        }
    }
    public static String getBalancedSubstring(String s, Character markStart, Character markEnd, Boolean includeMarkers) 
    {
        int level = 1;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == markStart) {
                level++;
            }
            else if (c == markEnd) {
                if (level == 1) {
                    return (includeMarkers ? markStart.toString() : "") + s.substring(0, (includeMarkers ? i + 1 : i));
                }
                if (level > 0) level--;
            }
        }
        return null;
    }
}

参见Java demo online