2013-06-12 25 views
8

比方說,我有一個像使用函數替換正則表達式子匹配

input := `bla bla b:foo="hop" blablabla b:bar="hu?"` 

字符串,我想用一個函數來替換引號之間的部分在b:foo="hop"b:bar="hu?"

它很容易建立一個正則表達式得到匹配和子匹配,例如

r := regexp.MustCompile(`\bb:\w+="([^"]+)"`) 

,然後調用ReplaceAllStringFunc但問題是,回調接收整場比賽,而不是子匹配:

fmt.Println(r.ReplaceAllStringFunc(input, func(m string) string { 
    // m is the whole match here. Damn. 
})) 

我該如何更換submatch?

現在,我還沒有找到一個更好的解決方案,而不是使用正則表達式在回調中分解我自己的m,並在處理子匹配後重新生成字符串。

我會使用一種替代方法,並在Go中使用它們,但事實並非如此(並且它們不應該是必需的)。

我能在這裏做什麼?


編輯:這是我目前的解決方案,我想簡化:

func complexFunc(s string) string { 
    return "dbvalue("+s+")" // this could be more complex 
} 
func main() { 
     input := `bla bla b:foo="hop" blablabla b:bar="hu?"` 
     r := regexp.MustCompile(`(\bb:\w+=")([^"]+)`) 
     fmt.Println(r.ReplaceAllStringFunc(input, func(m string) string { 
       parts := r.FindStringSubmatch(m) 
       return parts[1] + complexFunc(parts[2]) 
     })) 
} 

(playground link)

讓我困擾的是,我有兩次申請正則表達式。這聽起來不對。

+1

如果你認爲這是一個設計錯誤,隨意[文件​​錯誤](HTTP://代碼。 google.com/p/go/issues/list)。 – fuz

+0

@FUZxxl我不知道這是否是一個設計錯誤。它看起來不像我的最佳設計,但我可能會錯過簡單的一次通過解決方案。如果其他人在這裏評論,我可能會提交一個錯誤,但我需要意見。 –

+0

如果您有疑慮,提交錯誤幾乎肯定是一件好事。 – fuz

回答

1

我不喜歡的代碼波紋管,但似乎做你似乎什麼想做的事情:

package main 

import (
     "fmt" 
     "regexp" 
) 

func main() { 
     input := `bla bla b:foo="hop" blablabla b:bar="hu?"` 
     r := regexp.MustCompile(`\bb:\w+="([^"]+)"`) 
     r2 := regexp.MustCompile(`"([^"]+)"`) 
     fmt.Println(r.ReplaceAllStringFunc(input, func(m string) string { 
       return r2.ReplaceAllString(m, `"${2}whatever"`) 
     })) 
} 

Playground


輸出

bla bla b:foo="whatever" blablabla b:bar="whatever" 

編輯:採取二。


package main 

import (
     "fmt" 
     "regexp" 
) 

func computedFrom(s string) string { 
     return fmt.Sprintf("computedFrom(%s)", s) 
} 

func main() { 
     input := `bla bla b:foo="hop" blablabla b:bar="hu?"` 
     r := regexp.MustCompile(`\bb:\w+="([^"]+)"`) 
     r2 := regexp.MustCompile(`"([^"]+)"`) 
     fmt.Println(r.ReplaceAllStringFunc(input, func(m string) string { 
       match := string(r2.Find([]byte(m))) 
       return r2.ReplaceAllString(m, computedFrom(match)) 
     })) 
} 

Playground


輸出:

bla bla b:foo=computedFrom("hop") blablabla b:bar=computedFrom("hu?") 
+0

問題是我想用一個複雜的函數來計算子匹配的替換(以此子匹配作爲輸入),這就是爲什麼我不能簡單地使用裏面的ReplaceAllString。至於優雅,我擔心正確的解決方案會更糟:( –

+0

@dystroy:請參閱更新的答案。 – zzzz

+0

+1爲替代解決方案,但像我的這樣的力量使用兩個正則表達式,而技術上第一個包含所有內容。 –

相關問題