2013-06-12 16 views
8

मान लीजिए कि मैंएक समारोह का उपयोग कर एक नियमित अभिव्यक्ति submatch बदलें

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

तरह तार है और मैं एक समारोह का उपयोग कर b:foo="hop" या b:bar="hu?" में उद्धरण के बीच हिस्सों की जगह करना चाहते हैं।

यह मैच और submatch पाने के लिए एक नियमित अभिव्यक्ति, उदाहरण के

के लिए
r := regexp.MustCompile(`\bb:\w+="([^"]+)"`) 

और उसके बाद का निर्माण करने के ReplaceAllStringFunc फोन करने के लिए आसान है, लेकिन समस्या यह है कि कॉलबैक पूरे मैच प्राप्त करता है और नहीं submatch है:

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

मैं सबमिशन को कैसे बदल सकता हूं?

अभी, मुझे रीगेक्स के साथ कॉलबैक के अंदर m को विघटित करने और सबमिशन को संसाधित करने के बाद स्ट्रिंग को पुनर्निर्माण करने के बजाय बेहतर समाधान नहीं मिला है।

मैं गो में उपलब्ध सकारात्मक दृष्टिकोण के साथ एक वैकल्पिक दृष्टिकोण का उपयोग करता था लेकिन यह मामला नहीं है (और उन्हें वैसे भी आवश्यक नहीं होना चाहिए)।

मैं यहां क्या कर सकता हूं?


संपादित करें: यहाँ मेरे वर्तमान समाधान है कि मैं आसान बनाने के लिए चाहते हैं क्या है:

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)

क्या मुझे परेशान मैं regex दो बार लागू करने के लिए होता है। यह सही नहीं लगता है।

+1

आप मानते हैं कि यह एक डिजाइन ग़लती है, तो करने के लिए [बग के बारे में] (http के लिए स्वतंत्र महसूस: // कोड। google.com/p/go/issues/list)। – fuz

+0

@FUZxxl मुझे नहीं पता कि यह एक डिज़ाइन गलती है या नहीं। यह मेरे लिए इष्टतम डिजाइन की तरह नहीं दिखता है लेकिन मुझे एक साधारण एक-पास समाधान याद आ सकता है। यदि यहां अन्य लोग इस पर टिप्पणी करते हैं, तो मैं एक बग फाइल कर सकता हूं लेकिन मुझे राय चाहिए। –

+0

यदि आपको चिंता है तो एक बग दर्ज करना लगभग निश्चित रूप से एक अच्छी बात है। – fuz

उत्तर

1

मैं कोड bellow पसंद नहीं है, लेकिन यह है कि तुम क्या करना चाहते हैं लगता है ऐसा करने के लिए लगता है:

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" 

संपादित करें: II ले लो।


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 वैकल्पिक समाधान के लिए +1, लेकिन इस बल को दो रेगेक्स का उपयोग करने की तरह, जबकि तकनीकी रूप से पहले व्यक्ति में सब कुछ शामिल है। –

संबंधित मुद्दे