2013-06-12 4 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 внутри обратного вызова с регулярным выражением и перестроить строку после обработки отправки.

Я бы использовал альтернативный подход с положительным внешним видом, если бы они были доступны в Go, но это не так (и они не должны быть необходимы в любом случае).

Что я могу сделать здесь?


EDIT: вот мое текущее решение, которое я хотел бы упростить:

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" 

EDIT: Take 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 для альтернативного решения, но как у меня это заставляет использовать два регулярных выражения, тогда как технически первое содержит все. –

Смежные вопросы