2016-07-25 340 views
1

我有一個字符串,它有兩個關鍵字:「CURRENT NAME(S)」和「NEW NAME(S)」,每個關鍵字後跟一堆單詞。我想提取這些關鍵字以外的單詞集。用代碼詳細說明:Golang正則表達式匹配關鍵字對之間的多種模式

s := `"CURRENT NAME(S) 
Name1, Name2",,"NEW NAME(S) 
NewName1,NewName2"` 
    re := regexp.MustCompile(`"CURRENT NAME(S).*",,"NEW NAME(S).*"`) 

    segs := re.FindAllString(s, -1) 
    fmt.Println("segs:", segs) 

    segs2 := re.FindAllStringSubmatch(s, -1) 
    fmt.Println("segs2:", segs2) 

正如你所看到的,字符串's'有輸入。 「Name1,Name2」是當前名稱列表,「NewName1,NewName2」是新名稱列表。我想提取這兩個列表。這兩個列表用逗號分隔。每個關鍵字都以雙引號開頭,並且它們的覆蓋範圍在相應的雙引號結束時結束。

什麼是使用正則表達式,使程序可以打印「Name1, Name2」和「NewName1,NewName2」?

+0

檢查[此演示](https://play.golang.org/p/BuU54evLzJ),它看起來像你在找什麼? –

+0

是的,它的確如此。謝謝。你應該把它作爲答案,而不是評論。 –

+0

是的,我現在明白了:)非常感謝。 –

回答

1

你的正則表達式的問題是輸入字符串包含換行符號,而Go正則表達式中的.與換行符不匹配。另一個問題是.*是一個貪婪的模式,將m atch儘可能多的符號,因爲它可以達到最後第二個關鍵字。此外,您需要在正則表達式模式中轉義圓括號以匹配()文字符號。

解決問題的最佳辦法是改變.*成否定的字符類模式[^"]*並將其放置一對內部非轉義()形成捕獲組(一個結構得到子匹配從比賽)。

這裏是一個Go demo

package main 

import (
    "fmt" 
    "regexp" 
) 

func main() { 
    s := `"CURRENT NAME(S) 
Name1, Name2",,"NEW NAME(S) 
NewName1,NewName2"` 
    re := regexp.MustCompile(`"CURRENT NAME\(S\)\s*([^"]*)",,"NEW NAME\(S\)\s*([^"]*)"`) 

    segs2 := re.FindAllStringSubmatch(s,-1) 
    fmt.Printf("segs2: [%s; %s]", segs2[0][1], segs2[0][2]) 
} 

現在,正則表達式匹配:

  • "CURRENT NAME\(S\) - 一個文本字符串「當前名稱(S)`
  • \s* - 零個或多個空格
  • ([^"]*) - 第1組捕獲0+字符而不是"
  • ",,"NEW NAME\(S\) - 文字字符串",,"NEW NAME(S)
  • \s* - 零個或多個空格
  • ([^"]*) - 組2捕獲0+比"
  • "其它字符 - 字面"
1

如果你的輸入沒有改變,那麼最簡單的方法就是使用子匹配(組)。你可以嘗試這樣的事情:

// (?s) is a flag that enables '.' to match newlines 
var r = regexp.MustCompile(`(?s)CURRENT NAME\(S\)(.*)",,"NEW NAME\(S\)(.*)"`) 
fmt.Println(r.MatchString(s)) 
m := r.FindSubmatch([]byte(s)) // FindSubmatch requires []byte 

for _, match := range m { 
    s := string(match) 
    fmt.Printf("Match - %d: %s\n", i, strings.Trim(s, "\n")) //remove the newline 
} 

輸出:(請注意,第一場比賽是整個輸入字符串,因爲它完全正則表達式匹配(https://golang.org/pkg/regexp/#Regexp.FindSubmatch

Match - 0: CURRENT NAME(S) 
Name1, Name2",,"NEW NAME(S) 
NewName1,NewName2" 
Match - 1: Name1, Name2 
Match - 2: NewName1,NewName2 

例子:https://play.golang.org/p/0cgBOMumtp

+0

還有一個FindStringSubmatch,它接受一個字符串並返回一個字符串片段 – nussjustin

+0

這不會工作if輸入字符串中有兩對或更多關鍵字。 –

0

對於一個固定的格式就像在這個例子中一樣,您也可以避免使用正則表達式,並像本例中那樣執行顯式解析 - https://play.golang.org/p/QDIyYiWJHt

 
package main 

import (
    "fmt" 
    "strings" 
) 

func main() { 
    s := `"CURRENT NAME(S) 
Name1, Name2",,"NEW NAME(S) 
NewName1,NewName2"` 

    names := []string{} 
    parts := strings.Split(s, ",,") 
    for _, part := range parts { 
     part = strings.Trim(part, `"`) 
     part = strings.TrimPrefix(part, "CURRENT NAME(S)") 
     part = strings.TrimPrefix(part, "NEW NAME(S)") 
     part = strings.TrimSpace(part) 
     names = append(names, part) 
    } 
    fmt.Println("Names:") 
    for _, name := range names { 
     fmt.Println(name) 
    } 
} 

輸出:

 
Names: 
Name1, Name2 
NewName1,NewName2 

它使用的代碼幾行,而是可以更容易地理解,所述處理邏輯在第一一目瞭然。