正規

正規表現 の Go

1個の演習

正規表現について

regexpパッケージは、Goで正規表現を扱うための機能を提供します。

構文

受け入れられる正規表現の構文は、PerlやPythonなど他の言語で使われているものと同じ一般的な構文です。

検索パターンも入力テキストも、どちらもUTF-8として解釈されます。

バッククォート(`)で文字列を作る場合、バックスラッシュ(\)に特別な意味はなく、タブ\tや改行\nのような特殊文字の始まりを表すこともありません。

"\t\n" // regular string literal with 2 characters: a tab and a newline
`\t\n`// raw string literal with 4 characters: two backslashes, a 't', and an 'n'

このため、正規表現を作るときにはバッククォートを使うのが望ましいです。バックスラッシュをエスケープする必要がなくなるからです。

"\\" // string with a single backslash
`\\` // string with 2 backslashes

パターンのコンパイル:RegExp型

正規表現を使うには、まず文字列のパターンをコンパイルする必要があります。 ここでいうコンパイルとは、正規表現の文字列パターンを、扱いやすい内部表現に変換することを指します。 各パターンのコンパイルは一度だけ行えばよく、その後はコンパイル済みの正規表現を何度も使うことができます。 regexp.Regexp型は、コンパイル済みの正規表現を表します。 regexp.Compile関数を使うと、文字列パターンをregexp.Regexpにコンパイルできます。 コンパイルに失敗した場合、この関数はnilとエラーを返します。

re, err := regexp.Compile(`(a|b)+`)
fmt.Println(re, err) // => (a|b)+ <nil>
re, err = regexp.Compile(`a|b)+`)
fmt.Println(re, err) // => <nil> error parsing regexp: unexpected ): `a|b)+`

MustCompile関数は、Compileの代わりに使える便利な関数です。

re = regexp.MustCompile(`[a-z]+\d*`)

この関数を使えば、エラーを処理する必要はありません。

Caution

MustCompileは、パターンが確実にコンパイルできるとわかっている場合にだけ使ってください。そうでない場合、プログラムはパニックを起こします。

正規表現のメソッド

Regexpには、正規表現にマッチして一致したテキストを特定する16個のメソッドがあります。 これらの名前は、次の正規表現にマッチします。

Find(All)?(String)?(Submatch)?(Index)?
  • Allがある場合、そのメソッドは式全体に対する連続した重複しないマッチを探します。
  • Stringがある場合、引数は文字列です。ない場合はバイトのスライスになります。戻り値はそれに応じて調整されます。
  • Submatchがある場合、戻り値は式の連続した部分マッチを特定するスライスです。
  • Indexがある場合、マッチと部分マッチは入力文字列内のバイトインデックスのペアで特定されます。

また、次のためのメソッドもあります。

  • 正規表現のマッチを置換文字列で置き換える
  • 正規表現で区切られた文字列を分割する

全体として、regexpパッケージは40を超える関数とメソッドを定義しています。 以下では、いくつかのメソッドの使い方を示します。 これらやその他の関数の詳細については、APIドキュメントを参照してください。

MatchStringの例

MatchStringメソッドは、文字列に正規表現のマッチが含まれているかどうかを報告します。

re = regexp.MustCompile(`[a-z]+\d*`)
b = re.MatchString("[a12]")       // => true
b = re.MatchString("12abc34(ef)") // => true
b = re.MatchString(" abc!")       // => true
b = re.MatchString("123 456")     // => false

FindStringの例

FindStringメソッドは、正規表現に最も左でマッチしたテキストを保持する文字列を返します。

re = regexp.MustCompile(`[a-z]+\d*`)
s = re.FindString("[a12]")       // => "a12"
s = re.FindString("12abc34(ef)") // => "abc34"
s = re.FindString(" abc!")       // => "abc"
s = re.FindString("123 456")     // => ""

FindStringSubmatchの例

FindStringSubmatchメソッドは、正規表現に最も左でマッチしたテキストと、その部分式のマッチがあればそれらを保持する文字列のスライスを返します。 これは、キャプチャグループにマッチする文字列を特定するのに使えます。 戻り値がnilの場合、マッチしなかったことを示します。

re = regexp.MustCompile(`[a-z]+(\d*)`)
sl = re.FindStringSubmatch("[a12]")       // => []string{"a12","12"}
sl = re.FindStringSubmatch("12abc34(ef)") // => []string{"abc34","34"}
sl = re.FindStringSubmatch(" abc!")       // => []string{"abc",""}
sl = re.FindStringSubmatch("123 456")     // => <nil>

ReplaceAllStringの例

re.ReplaceAllString(src,repl)メソッドは、正規表現reのマッチを置換文字列replで置き換えたsrcのコピーを返します。

re = regexp.MustCompile(`[a-z]+\d*`)
s = re.ReplaceAllString("[a12]", "X")       // => "[X]"
s = re.ReplaceAllString("12abc34(ef)", "X") // => "12X(X)"
s = re.ReplaceAllString(" abc!", "X")       // => " X!"
s = re.ReplaceAllString("123 456", "X")     // => "123 456"

Splitの例

re.Split(s,n)メソッドは、テキストsを式で区切られた部分文字列に分割し、それらの式のマッチの間にある部分文字列のスライスを返します。 nは返す部分文字列の最大数を決めます。 n<0の場合、メソッドはすべての部分文字列を返します。

re = regexp.MustCompile(`[a-z]+\d*`)
sl = re.Split("[a12]", -1)      // => []string{"[","]"}
sl = re.Split("12abc34(ef)", 2) // => []string{"12","(ef)"}
sl = re.Split(" abc!", -1)      // => []string{" ","!"}
sl = re.Split("123 456", -1)    // => []string{"123 456"}

パフォーマンス

このパッケージが提供するregexpの実装は、入力のサイズに対して線形の時間で実行されることが保証されています。

注意点

regexpパッケージは、RE2正規表現を実装しています(\Cを除く)。 その構文はPCRE("Perl Compatible Regular Expression")とほぼ互換性がありますが、いくつかの違いがあります。 詳細については、こちらの記事の「Caveat section」を参照してください。

GitHubで編集 リンクは新しいウィンドウまたはタブで開きます

正規表現を学習する

練習はロックされています

正規表現を練習するには、あと2個の演習のロックを解除してください