正则表达式在Golang中命名组无法正确捕获

时间:2015-08-06 12:32:53

标签: regex go

我有以下字符串,它是我们网络上投影仪的发现数据包:

AMXB<-SDKClass=VideoProjector><-UUID=ABCDEFG><-Make=DELL><-Model=S300w><-Revision=0.2.0>

我尝试编写一些Golang代码,将其转换为地图,因此我可以调用details["UUID"]并让它返回ABCDEFG。我写了一个看起来像这样的正则表达式:

(?:UUID=)(?P<UUID>(.*?))>|(?:Make=)(?P<Make>(.*?))>|(?:Model=)(?P<Model>(.*?))>|(?:SDKClass=)(?P<SDKClass>(.*?))>

当我使用regex 101在线测试时,除了编号组外,它似乎匹配所有内容,但我很容易忽略这些:

  

MATCH 1

     

SDKClass [15-29] VideoProjector

     
      
  1. [15-29] VideoProjector
  2.   
  

MATCH 2

     

UUID [37-49] B8AC6FDFE1E2

     
      
  1. [37-49] B8AC6FDFE1E2
  2.   
  

MATCH 3

     

制作[57-61]戴尔

     
      
  1. [57-61]戴尔
  2.   
  

MATCH 4

     

型号[70-75] S300w

     
      
  1. [70-75] S300w
  2.   

但是当我在Golang中尝试时,我得到different results(注意:这些结果使用go-spew整理,以便于阅读):

([][]string) (len=4 cap=10) {
 ([]string) (len=9 cap=9) {
  (string) (len=24) "SDKClass=VideoProjector>",
  (string) "",
  (string) "",
  (string) "",
  (string) "",
  (string) "",
  (string) "",
  (string) (len=14) "VideoProjector",
  (string) (len=14) "VideoProjector"
 },
 ([]string) (len=9 cap=9) {
  (string) (len=18) "UUID=B8AC6FDFE1E2>",
  (string) (len=12) "B8AC6FDFE1E2",
  (string) (len=12) "B8AC6FDFE1E2",
  (string) "",
  (string) "",
  (string) "",
  (string) "",
  (string) "",
  (string) ""
 },
 ([]string) (len=9 cap=9) {
  (string) (len=10) "Make=DELL>",
  (string) "",
  (string) "",
  (string) (len=4) "DELL",
  (string) (len=4) "DELL",
  (string) "",
  (string) "",
  (string) "",
  (string) ""
 },
 ([]string) (len=9 cap=9) {
  (string) (len=12) "Model=S300w>",
  (string) "",
  (string) "",
  (string) "",
  (string) "",
  (string) (len=5) "S300w",
  (string) (len=5) "S300w",
  (string) "",
  (string) ""
 }
}

我的正则表达式有什么问题,我该如何解决?我已经尝试了几乎所有表达式的组合(我现在几乎是一个正则表达式大师:\)

2 个答案:

答案 0 :(得分:0)

据我所知,它的工作原理与你编写的完全一样,同样适用于regex101和Go。您观察到的差异仅仅是因为结果的呈现方式不同。

让我们仔细看看regex101返回的结果。例如,这一个:

Router::scope('/', function (\Cake\Routing\RouteBuilder $routes) {
    // ...

    $routes->connect('/users', ['controller' => 'Users', 'action' => 'index']);
    $routes->connect('/users/:action/*', ['controller' => 'Users']);

    $routes->connect('/foos', ['controller' => 'Foos', 'action' => 'index']);
    $routes->connect('/foos/:action/*', ['controller' => 'Users']);

    // and so on...
});

它基本上说它找到了两个子匹配,其中一个是命名的,另一个是索引8.让我们看一下Go:

MATCH 1
SDKClass    [15-29]  `VideoProjector`
8.          [15-29]  `VideoProjector`

它说它找到了第7组和第8组的两个子匹配。要获取组7的名称,您应该调用([]string) (len=9 cap=9) { (string) (len=24) "SDKClass=VideoProjector>", (string) "", (string) "", (string) "", (string) "", (string) "", (string) "", (string) (len=14) "VideoProjector", (string) (len=14) "VideoProjector" }, r.SubexpNames()将返回SDKClass r.SubexpNames()[7]

所以两者都返回相同的结果。

答案 1 :(得分:0)

所以在AlexAtNet的帮助下,我得到了答案 - 足以让我离开。这是我的最终代码:

r, _ := regexp.Compile("<-([^=]+)=([^>]+)>")

match := r.FindAllString(string(msg), -1)
result := make(map[string]string)

for _, p := range match {
    split := strings.Split(p, "=")
    result[split[0]] = split[1]
}

结果如下:

([]string) (len=4 cap=10) {
 (string) (len=23) "SDKClass=VideoProjector",
 (string) (len=17) "UUID=B8AC6FDFE1E2",
 (string) (len=9) "Make=DELL",
 (string) (len=11) "Model=S300w"
 (string) (len=14) "Revision=0.2.0"
}

但我可以通过Split()简单地=字符串,并获取属性名称和值。

我仍然在寻找对我的正则表达式和/或代码的改进,这样我就可以看到如何正确执行它而无需额外的拆分或过多的代码。