在golang regex中获取子组的命名列表

时间:2017-09-05 15:16:19

标签: regex go regex-group

我正在寻找一个返回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]。

1 个答案:

答案 0 :(得分:2)

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

另请注意,此引擎不会保留所有捕获组值 在量化的外部分组中,如(a|b|c)+,其中该组仅包含它找到的最后一个或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。验证您正在解析的表单。
这将验证并将所有多边形集作为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*\))

此步骤相当于查找所有类型的匹配。它应匹配在Single_Poly_All_Pts组字符串中返回的单个多边形的所有点的连续值。

这将为您提供这两个单独的匹配,可以将它们放入具有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