nasa9084
· 5 min read

Go言語で文字列を処理する

Go言語で文字列を処理する

Go言語のregexpパッケージを使用した正規表現の処理は、一般的なスクリプト言語の処理速度と同程度で、正規表現を使用しない処理に比べてパフォーマンスがよくありません[1]
そのため、可能であるならregexpパッケージを使用しないようにすべきです。
しかし、すべての処理を自分で書くのは大変です。
標準パッケージにも文字列を処理する関数が数多く用意されています。

strings パッケージ

stringsパッケージはその名の通り、文字列を取り扱うパッケージです。
UTF-8でエンコードされた文字列(普通の文字列)をそのまま取り扱います。

判別系

Contains

func Contains(s, substr string) bool

Contains関数は、sの中にsubstrが存在するかどうかを返します。
Pythonで言うところのsubstr in sに相当します。
正規表現ならば、substrとのmatchで真偽値をとることに相当します。

example

fmt.Println(strings.Contains("hogefugapiyo", "fuga"))
// Output: true

fmt.Println(strings.Contains("hogefugapiyo", "foo"))
// Output: false

ContainsAny

func ContainsAny(s, chars string) bool

ContainsAny関数はsの中に、charsに含まれる文字のいずれかが存在するかどうかを返します。
つまり、charsは文字列ですが、扱いとしては文字の配列であると考えた方が良いでしょう。

正規表現で表すなら、/[${chars}]/の様な表現と考えられます(${chars}は置き換える)。

example

fmt.Println(strings.ContainsAny("hogefugapiyo", "abcd"))
// Output: true

fmt.Println(strings.ContainsAny("hogefugapiyo", "1234"))
// Output: false

HasPrefix

func HasPrefix(s, prefix string) bool

HasPrefix関数は、sの頭がprefixと等しいかどうかを判別します。
正規表現で^を使った文字列マッチに相当します。

Prefixなのでマッチさせたい文字列をつい第一引数に与えたくなりますが、第二引数がPrefixです。

example

fmt.Println(strings.HasPrefix("hogefugapiyo", "hoge"))
// Output: true

fmt.Println(strings.HasPrefix("hogefugapiyo", "piyo"))
// Output: false

HasSuffix

func HasSuffix(s, suffix string) bool

HasSuffix関数は、HasPrefix関数と対になる関数で、sの末尾がsuffixと等しいかどうかを判別します。
正規表現で$を使った文字列マッチに相当します。

example

fmt.Println(strings.HasSuffix("hogefugapiyo", "piyo))
// Output: true

fmt.Println(strings.HasSuffix("hogefugapiyo", "hoge"))
// Output: false

分割系

Split

func Split(s, sep string) []string
func SplitN(s, sep string, n int) []string

Split関数は任意の区切り文字列sepsを分割し、分割した後の配列を返します。
SplitN関数では第三引数に分割されたあとの配列の長さを与えることができ、これを超えた分割は行わずに配列の最後の要素にまとめて入れられます。
SplitNnに負の値を入れると、無限回を意味することができ、SplitN(s, sep, -1)Split(s, sep)と等価です。

example

fmt.Println(strings.Split("hoge,fuga,piyo", ","))
// Output: [hoge fuga piyo]

fmt.Println(strings.SplitN("hoge,fuga,piyo", ",", 2))
// Output: [hoge fuga,piyo]

SplitAfter

func SplitAfter(s, sep string) []string
func SplitAfterN(s, sep string, n int) []string

SplitAfter及びSplitAfterN関数は、任意の文字列sep直後sを分割します。
Split及びSplitNとの違いは、区切った後の文字列に区切り文字が含まれるところでしょう。

example

fmt.Println(strings.SplitAfter("hoge,fuga,piyo", ","))
// Output: [hoge, fuga, piyo]

Fields

func Fields(s string) []string

Fields関数は、任意回数の空白文字[2]で文字列を分割します。
Splitに空白文字を与えた場合と違い、任意回数の連続する空白文字を一区切りとします(Splitでは固定回数しか指定できない)。

example

fmt.Println(strings.Fields("    hoge fuga   piyo           `))
// Output: [hoge fuga piyo]

結合系

Join

func Join(a []string, sep string) string

Join関数は文字列のスライスを一つの文字列に結合します。
その際、区切り文字としてsepを与えることができます。

example

fmt.Println(strings.Join([]string{
    "foo",
    "bar",
    "baz",
}, ", "))
// Output: foo, bar, baz

Repeat

func Repeat(s string, count int) string

Repeat関数はcountで与えた回数、sで与えた文字列を繰り返し、結合した文字列を返します。

Pythonでs * countに相当します。

example

fmt.Println(strings.Repeat("foo", 3))
// Output: foofoofoo

置換系

ToUpper

func ToUpper(s string) string

ToUpeer関数は、与えられた文字列をすべて大文字に置換した文字列を返します。
大文字、小文字の別を持たない文字は無視されます。

example

fmt.Println(strings.ToUpper("foo文字α"))
// Output: FOO文字Α

ToLower

func ToLower(s string) string

ToLower関数は与えられた文字列を小文字に置換したものを返します。

example

fmt.Println(strings.ToUpper("FOO文字Α")) // Αはαの大文字
// Output: foo文字α

Replace

func Replace(s, old, new string, n int) string

Replace関数は文字の置換をn回実施した文字列を返します。
シェルスクリプトでのecho ${s} | sed -e "s/${old}/${new}/"と同様です。

nは回数で、負の値を与えるとoldにマッチした部分をすべて置換します。

example

fmt.Println(strings.Replace("barbarbar", "ar", "az", 2))
// Output: bazbazbar

fmt.Println(strings.Replace("barbarbar", "ar", "az", -1))
// Output: bazbazbaz

Trim

func Trim(s string, cutset string) string

Trim関数は与えられた文字列の左右からcutsetに含まれる文字を削除します。
注意が必要なのは、文字列マッチでは無く、文字セットとのマッチだということです。
cutsetに含まれない文字の内側はチェックしません。

example

fmt.Print(strings.Trim("foobarbaz", "foaz"))
// Output: barb

TrimLeft/TrimRight

func TrimLeft(s string, cutset string) string
func TrinRight(s string, cutset string) string

TrimLeft関数とTrimRight関数はそれぞれ、Trim関数を右側または左側に制限したものです。
TrimLeft(TrimRight(s, cutset), cutset)Trim(s, cutset)と等価です。

example

fmt.Print(strings.TrimLeft("foobarbaz", "foaz"))
// Output: barbaz

fmt.Print(strings.TrimRight("foobarbaz", "foaz"))
// Output: foobarb

fmt.Print(strings.TrimLeft(strings.TrimRight("foobarbaz", "foaz"), "foaz"))
}
// Output: barb

TrimPrefix/TrimSuffix

func TrimPrefix(s, prefix string) string
func TrifSuffix(s, suffix string) string

TrimPrefix関数とTrimSuffix関数はそれぞれ、Prefix文字列とSuffix文字列を取り除きます。
TrimLeft関数、TrimRight関数との違いは、文字列マッチだと言うことです。
マッチしなかった場合は変更されていない文字列がそのまま返されます。

example

fmt.Println(strings.TrimPrefix("foobarbaz", "fo"))
// Output: obarbaz

strconv パッケージ

strconvパッケージは、文字列をある型の表現へと変換します。
ここでは二つの関数のみを紹介します。

Atoi

func Atoi(s string) (int, error)

Atoi関数は、与えられた文字列を10進数の整数文字列として解釈して変換した結果を返します。
10進数整数として解釈できなかった場合、エラーを返します。(値は0となります。)

strconv.ParseInt(s, 10, 0)の返値をint型にキャストしたものと等価な結果となります。

example

var i int
var err error
i, err = strconv.Atoi("1")
fmt.Println(i, err)
// Output: 1, <nil>

i, err = strconv.Atoi("0.1")
fmt.Println(i, err)
// Output: 0 strconv.Atoi: parsing "0.1": invalid syntax

Quote

func Quote(s string) string

Quote関数はダブルクォートで囲まれた、Goでの文字列のリテラル表現を返します。
改行などの表示されない文字は\nなどのエスケープシーケンスを使用して表現されます。

example

fmt.Println(strconv.Quote(`foobar
`))
// Output: "foobar\n"

unicode パッケージ

unicodeパッケージは、ユニコードの文字を処理するための関数が含まれています。
ここでは一つのみ紹介します。

IsXXX

IsXXX関数群はruneを引数にとり、その文字が所定のカテゴリ[3]に属するかどうかを判定します。
例えばIsGraphicであればGraphicカテゴリ(L, M, N, P, S, Zsのいずれか)に属するかどうか、IsNumberであればNumberカテゴリ(N)に属するかどうか、といった具合です。


  1. golangの正規表現は遅いのか? ↩︎

  2. unicode.IsSpaceで規定されたもの ↩︎

  3. Unicode Character Categories ↩︎