在 golang 正则表达式中获取子组的命名列表

Get named list of subgroup in golang regex

我正在寻找一个 returns a map[string]interface{} 的函数,其中 interface{} 可以是一个切片、一个 map[string]interface{} 或一个值。

我的用例是像下面这样解析 WKT 几何图形并检索点值;甜甜圈多边形示例:

POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0),(3 3, 3 7, 7 7, 7 3, 3 3))

正则表达式(出于可读性目的,我自愿设置 \d 只匹配整数):

(POLYGON \(
    (?P<polygons>\(
        (?P<points>(?P<point>(\d \d), ){3,})
        (?P<last_point>\d \d )\),)*
    (?P<last_polygon>\(
        (?P<points>(?P<point>(\d \d), ){3,})
        (?P<last_point>\d \d)\))\)
)

我有一个函数(从 SO 复制)可以检索一些信息,但它对嵌套组和组列表不是很好:

func getRegexMatchParams(reg *regexp.Regexp, url string) (paramsMap map[string]string) {
    match := reg.FindStringSubmatch(url)
    paramsMap = make(map[string]string)
    for i, name := range reg.SubexpNames() {
        if i > 0 && i <= len(match) {
            paramsMap[name] = match[i]
        }
    }
    return match
}

看来point组只得到1分。 example on playground

[编辑] 我想要的结果是这样的:

map[string]interface{}{
    "polygons": map[string]interface{} {
        "points": []interface{}{
            {map[string]string{"point": "0 0"}},     
            {map[string]string{"point": "0 10"}},        
            {map[string]string{"point": "10 10"}},        
            {map[string]string{"point": "10 0"}},
        },
        "last_point": "0 0",
    },
    "last_polygon": map[string]interface{} {
        "points": []interface{}{
            {map[string]string{"point": "3 3"}},     
            {map[string]string{"point": "3 7"}},        
            {map[string]string{"point": "7 7"}},        
            {map[string]string{"point": "7 3"}},
        },
        "last_point": "3 3",
    }
}

所以我可以将它进一步用于不同的目的,例如查询数据库并验证每个多边形的 last_point = points[0]。

尝试在正则表达式中添加一些空格。

另请注意,此引擎不会保留所有
在像 (a|b|c)+ 这样的量化外部分组中,该组将仅包含它找到的最后一个 a 或 b 或 c。

而且,您的正则表达式可以简化为

(POLYGON\s*\((?P<polygons>\(\s*(?P<points>(?P<point>\s*(\d+\s+\d+)\s*,){3,})\s*(?P<last_point>\d+\s+\d+)\s*\)(?:\s*,\s*|\s*\)))+)

https://play.golang.org/p/rLaaEa_7GX


原文:

(POLYGON\s*\((?P<polygons>\(\s*(?P<points>(?P<point>\s*(\d+\s+\d+)\s*,){3,})\s*(?P<last_point>\d+\s+\d+)\s*\),)*(?P<last_polygon>\(\s*(?P<points>(?P<point>\s*(\d+\s+\d+)\s*,){3,})\s*(?P<last_point>\d+\s+\d+)\s*\))\s*\))

https://play.golang.org/p/rZgJYPDMzl

请参阅下文了解这些组包含的内容。

 (                             # (1 start)
      POLYGON \s* \(
      (?P<polygons>                 # (2 start)
           \( \s* 
           (?P<points>                   # (3 start)
                (?P<point>                    # (4 start)
                     \s* 
                     ( \d+ \s+ \d+ )               # (5)
                     \s* 
                     , 
                ){3,}                         # (4 end)
           )                             # (3 end)
           \s*            
           (?P<last_point> \d+ \s+ \d+ )  # (6)
           \s* \),
      )*                            # (2 end)
      (?P<last_polygon>             # (7 start)
           \( \s* 
           (?P<points>                   # (8 start)
                (?P<point>                    # (9 start)
                     \s* 
                     ( \d+ \s+ \d+ )               # (10)
                     \s* 
                     , 
                ){3,}                         # (9 end)
           )                             # (8 end)
           \s* 
           (?P<last_point> \d+ \s+ \d+ )  # (11)
           \s* \)
      )                             # (7 end)
      \s* \)
 )                             # (1 end)

输入

POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0),(3 3, 3 7, 7 7, 7 3, 3 3))

输出

 **  Grp 0                -  ( pos 0 , len 65 ) 
POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0),(3 3, 3 7, 7 7, 7 3, 3 3))  
 **  Grp 1                -  ( pos 0 , len 65 ) 
POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0),(3 3, 3 7, 7 7, 7 3, 3 3))  
 **  Grp 2 [polygons]     -  ( pos 9 , len 30 ) 
(0 0, 0 10, 10 10, 10 0, 0 0),  
 **  Grp 3 [points]       -  ( pos 10 , len 23 ) 
0 0, 0 10, 10 10, 10 0,  
 **  Grp 4 [point]        -  ( pos 27 , len 6 ) 
 10 0,  
 **  Grp 5                -  ( pos 28 , len 4 ) 
10 0  
 **  Grp 6 [last_point]   -  ( pos 34 , len 3 ) 
0 0  
 **  Grp 7 [last_polygon] -  ( pos 39 , len 25 ) 
(3 3, 3 7, 7 7, 7 3, 3 3)  
 **  Grp 8 [points]       -  ( pos 40 , len 19 ) 
3 3, 3 7, 7 7, 7 3,  
 **  Grp 9 [point]        -  ( pos 54 , len 5 ) 
 7 3,  
 **  Grp 10                -  ( pos 55 , len 3 ) 
7 3  
 **  Grp 11 [last_point]   -  ( pos 60 , len 3 ) 
3 3  

可能的解决方案

并非不可能。它只需要几个额外的步骤。
(顺便说一句,WKT 没有可以为您解析的库吗?)

现在,我不知道你的语言能力,所以这只是一个通用的方法。

1。验证您正在解析的表单。
这将验证 return 所有多边形集 作为 All_Polygons 组中的单个字符串。

目标POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0),(3 3, 3 7, 7 7, 7 3, 3 3))

POLYGON\s*\((?P<All_Polygons>(?:\(\s*\d+\s+\d+(?:\s*,\s*\d+\s+\d+){2,}\s*\))(?:\s*,\(\s*\d+\s+\d+(?:\s*,\s*\d+\s+\d+){2,}\s*\))*)\s*\)

 **  Grp 1 [All_Polygons] -  ( pos 9 , len 55 ) 
(0 0, 0 10, 10 10, 10 0, 0 0),(3 3, 3 7, 7 7, 7 3, 3 3)

2。如果 1 成功,则使用 All_Polygons 字符串的输出设置循环匹配。

目标(0 0, 0 10, 10 10, 10 0, 0 0),(3 3, 3 7, 7 7, 7 3, 3 3)

(?:\(\s*(?P<Single_Poly_All_Pts>\d+\s+\d+(?:\s*,\s*\d+\s+\d+){2,})\s*\))

这一步相当于查找所有类型的匹配项。它应该匹配单个多边形所有点的连续值,returned in Single_Poly_All_Pts group string。

这将为您提供这 2 个单独的匹配项,它们可以放入具有 2 个值字符串的临时数组中:

 **  Grp 1 [Single_Poly_All_Pts] -  ( pos 1 , len 27 ) 
0 0, 0 10, 10 10, 10 0, 0 0  

 **  Grp 1 [Single_Poly_All_Pts] -  ( pos 31 , len 23 ) 
3 3, 3 7, 7 7, 7 3, 3 3  

3。如果 2 成功,则使用步骤 2 的临时数组输出设置循环匹配。
这将为您提供每个多边形的 点。

(?P<Single_Point>\d+\s+\d+)

这又是一个循环匹配(或查找所有类型的匹配)。对于每个数组元素
(多边形),这将产生单独的点。

目标[元素 1] 0 0, 0 10, 10 10, 10 0, 0 0

 **  Grp 1 [Single_Point] -  ( pos 0 , len 3 ) 
0 0  
 **  Grp 1 [Single_Point] -  ( pos 5 , len 4 ) 
0 10  
 **  Grp 1 [Single_Point] -  ( pos 11 , len 5 ) 
10 10  
 **  Grp 1 [Single_Point] -  ( pos 18 , len 4 ) 
10 0  
 **  Grp 1 [Single_Point] -  ( pos 24 , len 3 ) 
0 0  

并且,

目标[元素 2] 3 3, 3 7, 7 7, 7 3, 3 3

 **  Grp 1 [Single_Point] -  ( pos 0 , len 3 ) 
3 3  
 **  Grp 1 [Single_Point] -  ( pos 5 , len 3 ) 
3 7  
 **  Grp 1 [Single_Point] -  ( pos 10 , len 3 ) 
7 7  
 **  Grp 1 [Single_Point] -  ( pos 15 , len 3 ) 
7 3  
 **  Grp 1 [Single_Point] -  ( pos 20 , len 3 ) 
3 3