追記
下記の記事では、後方参照を使用する方法はないという内容になっていますが、
最新バージョンでは使用できるようになっています。
replace.go
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile("a(x*)b")
fmt.Println(re.ReplaceAllString("-ab-axxb-", "$1"))
}
参考
regexp
パッケージのページをざっと確認したところ、
\1
や$1
などの後方参照を行う方法がないようなので、
ReplaceAllStringFunc
関数とFindAllStringSubmatch
関数を用いて、
置換処理を行うことにした。
ReplaceAllStringFunc
関数は、マッチした各文字列を処理し変換後文字列を返す無名関数を設定する仕様になっている。
FindAllStringSubmatch
関数は、正規表現中の丸括弧()で囲った文字列を返してくれる。後方参照の代替として使用。
replace.go
package main
import (
"fmt"
"regexp"
)
func main() {
// タグから置換するデータ
var data = map[string]string{
"NAME": "Tarou",
"AGE": "30",
}
// テンプレート
template := "名前は{T_NAME}。年齢は{T_AGE}歳。{T_HOGEHOGE}"
// 正規表現
regex_str := "{T_([A-Z]+?)}"
re, err := regexp.Compile(regex_str)
if err != nil {
panic(err)
}
// 置換処理用関数
cb := func(s string) string {
// 正規表現の「([A-Z]+?)」の部分を取得
tname := re.FindStringSubmatch(s)
if len(tname) == 2 {
// タグ名に応じてデータを置換する
if ret := data[tname[1]]; ret != "" {
return ret
} else {
return s
}
}
return s
}
// 置換処理
ret := re.ReplaceAllStringFunc(template, cb)
// 結果表示
fmt.Println(ret)
}
今回の調査のために書いたregexp
の関数サンプルと実行結果を載せておく。
基本的に、[]bytes
型とstring
型のそれぞれに対して、同じ機能を備えた関数が用意されている。
関数名にString
が含まれている関数は、string
型を渡し、
含まれていない関数は、[]byte
型を渡すようになっている。
replace.go
package main
import (
"fmt"
"regexp"
)
func main() {
str := "テスト1{T_NAME}テスト2{T_AGE}テスト3"
re, err := regexp.Compile("{T_(.+?)}")
if err != nil {
panic(err)
}
fmt.Println("---------- Find ------------")
fmt.Println(string(re.Find([]byte(str))))
fmt.Println("---------- FindAll ------------")
rets_findall := re.FindAll([]byte(str), -1)
for _, ret := range rets_findall {
fmt.Println(string(ret))
}
fmt.Println("---------- FindAllIndex ------------")
rets_findallindex := re.FindAllIndex([]byte(str), -1)
for _, ret := range rets_findallindex {
fmt.Println(ret)
}
fmt.Println("---------- FindAllString ------------")
rets_findallstring := re.FindAllString(str, -1)
for _, ret := range rets_findallstring {
fmt.Println(ret)
}
fmt.Println("---------- FindAllStringIndex ------------")
rets_findallstringindex := re.FindAllStringIndex(str, -1)
for _, ret := range rets_findallstringindex {
fmt.Println(ret)
}
fmt.Println("---------- FindAllStringSubmatch ------------")
rets_findallstringsubmatch := re.FindAllStringSubmatch(str, -1)
for _, ret := range rets_findallstringsubmatch {
fmt.Println(ret)
}
fmt.Println("---------- FindAllStringSubmatchIndex ------------")
rets_findallstringsubmatchindex := re.FindAllStringSubmatchIndex(str, -1)
for _, ret := range rets_findallstringsubmatchindex {
fmt.Println(ret)
}
fmt.Println("---------- FindIndex ------------")
rets_findindex := re.FindIndex([]byte(str))
fmt.Println(rets_findindex)
fmt.Println("---------- FindString ------------")
rets_findstring := re.FindString(str)
fmt.Println(rets_findstring)
fmt.Println("---------- FindStringIndex ------------")
rets_findstringindex := re.FindStringIndex(str)
fmt.Println(rets_findstringindex)
fmt.Println("---------- FindStringSubmatch ------------")
rets_findstringsubmatch := re.FindStringSubmatch(str)
fmt.Println(rets_findstringsubmatch)
fmt.Println("---------- FindStringSubmatchIndex ------------")
rets_findstringsubmatchindex := re.FindStringSubmatchIndex(str)
fmt.Println(rets_findstringsubmatchindex)
fmt.Println("---------- FindSubmatch ------------")
rets_findsubmatch := re.FindSubmatch([]byte(str))
fmt.Println(rets_findsubmatch)
fmt.Println("---------- FindSubmatchIndex ------------")
rets_findsubmatchindex := re.FindSubmatchIndex([]byte(str))
fmt.Println(rets_findsubmatchindex)
fmt.Println("---------- Match ------------")
rets_match := re.Match([]byte(str))
fmt.Println(rets_match)
fmt.Println("---------- MatchString ------------")
rets_matchstring := re.MatchString(str)
fmt.Println(rets_matchstring)
fmt.Println("---------- NumSubexp ------------")
rets_numsubexp := re.NumSubexp()
fmt.Println(rets_numsubexp)
fmt.Println("---------- ReplaceAll ------------")
rets_replaceall := re.ReplaceAll([]byte(str), []byte("REPLACE"))
fmt.Println(string(rets_replaceall))
fmt.Println("---------- ReplaceAllFunc ------------")
rets_replaceallfunc := re.ReplaceAllFunc([]byte(str), func(b []byte) []byte { fmt.Println(string(b)); return []byte("REPLACE") })
fmt.Println(string(rets_replaceallfunc))
fmt.Println("---------- ReplaceAllString ------------")
rets_replaceallstring := re.ReplaceAllString(str, "REPLACE")
fmt.Println(rets_replaceallstring)
fmt.Println("---------- ReplaceAllStringFunc ------------")
rets_replaceallstringfunc := re.ReplaceAllStringFunc(str, func(s string) string { fmt.Println(s); return "REPLACE" })
fmt.Println(rets_replaceallstringfunc)
}
result
--------- Find ------------
{T_NAME}
---------- FindAll ------------
{T_NAME}
{T_AGE}
---------- FindAllIndex ------------
[10 18]
[28 35]
---------- FindAllString ------------
{T_NAME}
{T_AGE}
---------- FindAllStringIndex ------------
[10 18]
[28 35]
---------- FindAllStringSubmatch ------------
[{T_NAME} NAME]
[{T_AGE} AGE]
---------- FindAllStringSubmatchIndex ------------
[10 18 13 17]
[28 35 31 34]
---------- FindIndex ------------
[10 18]
---------- FindString ------------
{T_NAME}
---------- FindStringIndex ------------
[10 18]
---------- FindStringSubmatch ------------
[{T_NAME} NAME]
---------- FindStringSubmatchIndex ------------
[10 18 13 17]
---------- FindSubmatch ------------
[[123 84 95 78 65 77 69 125] [78 65 77 69]]
---------- FindSubmatchIndex ------------
[10 18 13 17]
---------- Match ------------
true
---------- MatchString ------------
true
---------- NumSubexp ------------
1
---------- ReplaceAll ------------
テスト1REPLACEテスト2REPLACEテスト3
---------- ReplaceAllFunc ------------
{T_NAME}
{T_AGE}
テスト1REPLACEテスト2REPLACEテスト3
---------- ReplaceAllString ------------
テスト1REPLACEテスト2REPLACEテスト3
---------- ReplaceAllStringFunc ------------
{T_NAME}
{T_AGE}
テスト1REPLACEテスト2REPLACEテスト3
参考
regexp パッケージ
http://golang.jp/pkg/regexp