正規表現

正規表現 #

文字列がパターンにマッチするか判定する #

単純なパターンマッチには func MatchString(pattern string, s string) (matched bool, err error) が使える。

文字列 s がパターン pattern にマッチしたら matched が true になる。

package main

import (
	"fmt"
	"regexp"
)

func main() {
	// マッチする場合
	ok, err := regexp.MatchString(`^h`, "hello world")
	fmt.Println(ok, err) // == true <nil>

	// マッチしない場合
	ok, err = regexp.MatchString(`^h`, "Hello world")
	fmt.Println(ok, err) // == false <nil>

	// 正規表現が不正な場合はエラーが返る
	ok, err = regexp.MatchString(`(aaa`, "hello world")
	fmt.Println(ok, err) // == false error parsing regexp: missing closing ): `(aaa`
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: regexp

正規表現オブジェクトを初期化する #

パターンマッチを繰り返し行う場合やパターンによる置換やマッチした文字列の取得など行う場合は、正規表現パターンをコンパイルしてオブジェクト化して利用する。

正規表現オブジェクトの初期化には func Compile(expr string) (*Regexp, error) を使う。

package main

import (
	"fmt"
	"regexp"
)

func main() {
	// 初期化
	re, err := regexp.Compile(`a+`)
	fmt.Println(re, err) // == a+ <nil>

	// パターンマッチは `func (re *Regexp) Match(b []byte) bool` で行う
	fmt.Println(re.MatchString("aaa")) // == true
	fmt.Println(re.MatchString("bbb")) // == false

	// 正規表現が不正な場合はエラーが返る
	re, err = regexp.Compile(`(b`)
	fmt.Println(re, err) // == <nil> error parsing regexp: missing closing ): `(b`

	// 使い捨てのコードやサンプルコードなどでエラー処理が不要な場合は `func MustCompile(str string) *Regexp` で正規表現オブジェクトの初期化をすることもできる
	// MustCompile は error を返さず手軽に扱えるが、エラーになった場合に panic を発生させるので実用には向かない
	re = regexp.MustCompile(`(c`) // => panic: regexp: Compile(`(c`): error parsing regexp: missing closing ): `(c`
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: regexp

パターンにマッチした文字列を取得する #

パターンにマッチした文字列を取得したい場合は func (re *Regexp) FindAllString(s string, n int) []string を使う。

引数 n はマッチさせる回数で -1 を指定すると回数無制限で全ての文字をマッチさせる。

package main

import (
	"fmt"
	"regexp"
)

func main() {
	re := regexp.MustCompile(`a+`)

	fmt.Println(re.FindAllString("abaabb", -1))       // == [a aa]
	fmt.Println(re.FindAllString("abaabbaaabbb", -1)) // == [a aa aaa aaaa]
	fmt.Println(re.FindAllString("ccc", -1))          // == []
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: regexp

パターン中のキャプチャブループにマッチした文字列を取得する #

パターン中のキャプチャグループにマッチした文字列を取得したい場合は func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string を使う。

引数 n はマッチさせる回数で -1 を指定すると回数無制限で全ての文字をマッチさせる。

matched は [[パターン全体にマッチした文字列, キャプチャブループにマッチした文字列...]...] という構造になる。

package main

import (
	"fmt"
	"regexp"
)

func main() {
	re := regexp.MustCompile(`a(a*)`)

	matched := re.FindAllStringSubmatch("abaabbaaabbb", -1)

	fmt.Printf("%#v\n", matched) // == [][]string{[]string{"a", ""}, []string{"aa", "a"}}

	// マッチしない場合は nil になる
	fmt.Printf("%#v\n", re.FindAllStringSubmatch("ccc", -1)) // == [][]string(nil)
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: regexp

パターンにマッチした文字列を置換する #

パターンマッチした文字列を置換したい場合は func (re *Regexp) ReplaceAllString(src, repl string) string を使う。

package main

import (
	"fmt"
	"regexp"
)

func main() {
	re := regexp.MustCompile(`a+`)

	replaced := re.ReplaceAllString("abaabbaaabbb", "A")
	fmt.Println(replaced) // == AbAbbAbbb
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: regexp

区切り文字をパターンで指定して文字列を分割する #

文字列をパターンで分割する場合は func (re *Regexp) Split(s string, n int) []string を使う。

n はマッチ回数で -1 にすれば無制限になる。

package main

import (
	"fmt"
	"regexp"
)

func main() {
	re := regexp.MustCompile(`a+`)

	list := re.Split("abaabbaaabbb", -1)
	fmt.Printf("%#v", list) // == []string{"", "b", "bb", "bbb"}
}

play_circleRun open_in_newRun In The Playground

参考ドキュメント: regexp