Go 言語(以下 Golang)で、文字列内の文字間にある複数スペースやタブを 1 つに変換したい。ついでに、全角スペースも。
つまり、単語間の空白を詰めたいのです。
" Hello, World ! " --> "Hello, World !"
"Hello,\tWorld ! " --> "Hello, World !"
" \t\n\t Hello,\tWorld\n!\n\t" --> "Hello, World !"
# 以下は全角スペース
" Hello, World! " --> "Hello, World!"
「golang 文字間の複数スペースを削除する」でググっても、正規表現や strings.ReplaseAll
を使った方法だったり、文字列の前後のトリムばかりだったので、自分のググラビリティとして。
TL; DR (今北産業)
- strings.Fields 関数を使う。
-
strings.Fields()
は、連続したホワイト・スペース(空白、タブや改行)を 1 つとして扱う strings.Split 関数の親戚。 -
strings.Fields()
で分解し、strings.Join()
で再度組み合わせると単語間の空白を詰められる。
// TrimWordGaps は、文字列内の連続した空白文字を 1 文字のスペースに変換します。
// 具体的な使い方・サンプルは TS; DR 参照
func TrimWordGaps(s string) string {
return strings.Join(strings.Fields(s), " ")
}
TS; DR
strings.Fields
とは
func Fieldsfunc Fields(s string) []string
Fields splits the string
s
around each instance of one or more consecutive white space characters, as defined byunicode.IsSpace
, returning a slice of substrings of s or an empty slice if s contains only white space.
(Fields | strings @ pkg.go.dev より)【筆者訳】
Fields
は、1 つ以上の連続したホワイト・スペースで囲まれている文字の周りで文字列s
を分割し、その部分文字列のスライスを返します。また、s
が空白のみを含む場合は空のスライスを返します。なお、ホワイト・スペースは unicode.IsSpaceで定義されている空白文字です。
つまり、strings.Fields()
は strings.Slice()
の変形バージョンです。
例えば strings.Slice(s, " ")
は、s
内でヒットした "
" ごとに分割するのに対し、strings.Fields(s)
は連続している空白文字(ホワイトスペース)を 1 文字として扱い s
を分割します。
動作サンプル
package main
import (
"fmt"
"strings"
"testing"
)
func TrimWordGaps(s string) string {
return strings.Join(strings.Fields(s), " ")
}
func ExampleTrimWordGaps() {
result := TrimWordGaps(" Hello, World ! ")
fmt.Println(result)
// Output: Hello, World !
}
func TestTrimWordGaps(t *testing.T) {
for i, test := range []struct {
input string
expect string
}{
{
input: " Hello, World ! ",
expect: "Hello, World !",
},
{
input: "Hello,\tWorld ! ",
expect: "Hello, World !",
},
{
input: " \t\n\t Hello,\tWorld\n!\n\t",
expect: "Hello, World !",
},
{
// 全角スペース入り
input: " Hello, World! ",
expect: "Hello, World!",
},
} {
nameTest := fmt.Sprintf("test #%d (Input:%#v)", i, test.input)
t.Run(nameTest, func(t *testing.T) {
actual := TrimWordGaps(test.input)
if test.expect != actual {
t.Fail()
}
})
}
}
// Output:
// === RUN TestTrimWordGaps
// === RUN TestTrimWordGaps/test_#0_(Input:"_Hello,___World__!_")
// === RUN TestTrimWordGaps/test_#1_(Input:"Hello,\tWorld_!_")
// === RUN TestTrimWordGaps/test_#2_(Input:"_\t\n\t_Hello,\tWorld\n!\n\t")
// === RUN TestTrimWordGaps/test_#3_(Input:"\u3000\u3000\u3000\u3000\u3000Hello,\u3000\u3000World!\u3000\u3000")
// --- PASS: TestTrimWordGaps (0.00s)
// --- PASS: TestTrimWordGaps/test_#0_(Input:"_Hello,___World__!_") (0.00s)
// --- PASS: TestTrimWordGaps/test_#1_(Input:"Hello,\tWorld_!_") (0.00s)
// --- PASS: TestTrimWordGaps/test_#2_(Input:"_\t\n\t_Hello,\tWorld\n!\n\t") (0.00s)
// --- PASS: TestTrimWordGaps/test_#3_(Input:"\u3000\u3000\u3000\u3000\u3000Hello,\u3000\u3000World!\u3000\u3000") (0.00s)
// === RUN ExampleTrimWordGaps
// --- PASS: ExampleTrimWordGaps (0.00s)
// PASS
- オンラインで動作をみる @ Go playground
- 動作確認: Go 1.18, 1.19, 1.22
参考文献
- Fields | strings @ pkg.go.dev
- How to remove redundant spaces/whitespace from a string in Golang? @ Stackoverflow