golang字符串相关处理

琴声何在 生死难猜 用一生去等待

文字列を結合する

1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
a := "Hello"
b := a + " World"
fmt.Println(b)
}

繰り返し文字列を生成する

1
2
3
4
5
6
7
8
9
package main

import "fmt"
import "strings"

func main() {
s := "Hey "
fmt.Println(strings.Repeat(s, 3))
}

大文字・小文字に揃える

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"
import "strings"

func main() {
s := "I love GoLang"
fmt.Println(strings.ToUpper(s))
fmt.Println(strings.ToLower(s))
}

大文字と小文字の入れ替え

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import "fmt"
import "strings"

func main() {
//うーん、かなりイマイチ
s := "i lOVE gOLANG"
sr := ""
for _, x := range s {
xs := string(x)
u := strings.ToUpper(xs)
l := strings.ToLower(xs)
if u == xs {
sr += l
} else if l == xs {
sr += u
} else {
sr += xs
}
}
fmt.Println(sr)
}

コマンドの実行結果を文字列に

1
2
3
4
5
6
7
8
9
package main

import "fmt"
import "os/exec"

func main() {
out, _ := exec.Command("date").Output()
fmt.Println(string(out))
}

複数行の文字列を作成する

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"

func main() {
s := `
This is a test.

GoLang, programming language developed at Google.
`
fmt.Println(s)
}

ヒアドキュメントの終端文字列をインデントする

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import "fmt"
import . "github.com/MakeNowJust/heredoc/dot"

func main() {
s := D(`
This is a test.

GoLang, programming language developed at Google.
`)
fmt.Println(s)
}

複数行のコマンドの実行結果を文字列に設定する

exec.Command()を使います。 (echoはシェル組み込みコマンドのせいか実行されない。。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"
import "os/exec"

func main() {
s := D(`
date
echo "-----------------------------"
ps
`)
outs := ""
for _, s = range strings.Split(s, "\n") {
out, _ := exec.Command(s).Output()
outs += string(out)
}
fmt.Println(outs)
}

部分文字列を取り出す

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"

func main() {
s := "Apple Banana Orange"
fmt.Println(s[0:5]) // => Apple
fmt.Println(s[6:(6 + 6)]) // => Banana
fmt.Println(s[0:3]) // => App
fmt.Println(s[6]) // => 66
fmt.Println(s[13:19]) // => Orange
}

部分文字列を置き換える

(うーんいまいち。。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"
import "strings"

func main() {
s := "Apple Banana Orange"
ss := strings.Split(s, "")
srep := strings.Split("Vine ", "")
for i, _ := range srep {
ss[i] = srep[i]
}

fmt.Println(strings.Join(ss, ""))
}

文字列中の式を評価し値を展開する

intなら%dでもよいですが、型推定をよさげに行うのなら%vが使えます。

1
2
3
4
5
6
7
8
package main

import "fmt"

func main() {
value := 123
fmt.Printf("value is %v\n", value)
}

文字列を1文字ずつ処理する

こちらによると、 string[n]だとbyte単位、rangeで回すとrune(utf-8文字)単位らしいです。

1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"

func main() {
sum := 0
for _, c := range "Golang" {
sum = sum + int(c)
}
fmt.Println(sum)
}

文字列の先頭と末尾の空白文字を削除する

空白ならTrimSpace, 任意の文字でやりたければTrimでやれます。

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"
import "strings"

func main() {
s := " Hello, Golang! "
s = strings.TrimSpace(s)
fmt.Println(s)
}

文字列を整数に変換する (to_i)

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"
import "strconv"

func main() {
i := 1
s := "999"
si, _ := strconv.Atoi(s)
i = i + si
fmt.Println(i)
}

文字列を浮動小数点に変換する (to_f)

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"
import "strconv"

func main() {
s := "10"
sf, _ := strconv.ParseFloat(s, 64) //64 bit float
fmt.Println(sf)
}

8進文字列を整数に変換する

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"
import "strconv"

func main() {
s := "010"
so, _ := strconv.ParseInt(s, 8, 64) // base 8, 64bit
fmt.Println(so)
}

16進文字列を整数に変換する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

import "strconv"

func main() {
s := "ff" // 0xは含んではいけません。
sh, _ := strconv.ParseInt(s, 16, 64)
fmt.Println(sh)

s = "0xff" // 0xを含んでも良い
sh, _ = strconv.ParseInt(s, 0, 64)
fmt.Println(sh)

}

ASCII文字をコード値に(コード値をASCII文字に)変換する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import "fmt"

func main() {
s := "ABC"
fmt.Println(s[0])
fmt.Println(string(82))
}
```

### 文字列を中央寄せ・左詰・右詰する
```go
package main

import "fmt"
import "strings"

func main() {
//右詰、左詰めはformat文字列が対応しています。±で指定。
s := "Go"
fmt.Printf("%10s\n", s)
fmt.Printf("%-10s\n", s)

//センタリングはなさそうです。
l := 10
ls := (l - len(s)) / 2
cs := strings.Repeat(" ", ls) + s + strings.Repeat(" ", l-(ls+len(s)))
fmt.Println(cs)
}

“次”の文字列を取得する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package main

import "fmt"

func main() {
fmt.Println(succ("9")) // => "10"
fmt.Println(succ("a")) // => "b"
fmt.Println(succ("AAA")) // => "AAB"
fmt.Println(succ("A99")) // => "B00"
fmt.Println(succ("A099")) // => "A100"
}

// 文字列を反転して返す
func reverse(s string) string {
ans := ""
for i, _ := range s {
ans += string(s[len(s)-i-1])
}
return string(ans)
}

// "次"の文字列を取得する
func succ(s string) string {
r := reverse(s)
ans := ""
carry := 1
lastLetter := string(r[0])
for i, _ := range r {
lastLetter = string(r[i])
a := lastLetter
if carry == 1 {
if lastLetter == "z" {
a = "a"
carry = 1
} else if lastLetter == "Z" {
a = "A"
carry = 1
} else if lastLetter == "9" {
a = "0"
carry = 1
} else {
if r[i] == 0 {
a = "1"
} else {
a = string(r[i] + 1)
carry = 0
}
}
}
ans += a
}
if carry == 1 {
if lastLetter == "9" {
ans += "1"
} else if lastLetter == "z" {
ans += "a"
} else if lastLetter == "Z" {
ans += "A"
}
}
return reverse(ans)
}

文字列を暗号化する

とりあえずMD5あたりの例を書いておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import "fmt"
import "crypto/md5"
import "io"
import "bufio"

func main() {
h := md5.New()
io.WriteString(h, "hogehoge")

fmt.Print("input password >")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()

h2 := md5.New()
io.WriteString(h2, scanner.Text())

if h2.Sum(nil)[0] == h.Sum(nil)[0] {
fmt.Println("right")
} else {
fmt.Println("wrong")
}

}

文字列中で指定したパターンにマッチする部分を置換する

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"
import "strings"

func main() {
s := "Apple Banana Apple Orange"
s = strings.Replace(s, "Apple", "Pine", 1) // 最後の引数は回数
fmt.Println(s)
s = strings.Replace(s, "Apple", "Pine", -1) // <0で無制限
fmt.Println(s)
}

文字列中に含まれている任意文字列の位置を求める

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"
import "strings"

func main() {
s := "Apple Banana Apple Orange"
fmt.Println(strings.Index(s, "Apple")) // => 0
fmt.Println(strings.Index(s, "Banana")) // => 6
// 途中から検索する方法は無いのでスライスで渡す
fmt.Println(strings.Index(s[6:], "Apple") + 6) // => 13
// 後方検索はLastIndex()
fmt.Println(strings.LastIndex(s, "Apple")) // => 13
fmt.Println(strings.Index(s[:(len(s)-6)], "Apple")) // => 0
}

文字列の末端の改行を削除する

1
2
3
4
5
6
7
8
9
10
package main

import "fmt"
import "strings"

func main() {
s := "Hello, Golang!\n"
s = strings.TrimRight(s, "\n")
fmt.Println(s)
}

カンマ区切りの文字列を扱う

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import "fmt"
import "strings"

func main() {

s := "001,ASHITANI Tatsuji,Yokohama"
slice := strings.Split(s, ",")
for _, x := range slice {
fmt.Println(x)
}
}

任意のパターンにマッチするものを全て抜き出す

1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"
import "regexp"

func main() {
s := "hoge:045-111-2222 boke:045-222-2222"
re, _ := regexp.Compile("(\\S+):([\\d\\-]+)")
ans := re.FindAllStringSubmatch(s, -1) // [マッチした全体,1個目のカッコ,2個目のカッコ,..]の配列
fmt.Println(ans)
}

漢字コードを変換する

下記はEUCの例です。 指定するコーディングは、EUCJP,ISO2022JP,ShiftJISのどれかです。
こちらでご指摘いただいた点を 修正しました。’EUCJP’は’japanese.EUCJP’と呼びます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package main

import "fmt"
import "golang.org/x/text/encoding/japanese"
import "golang.org/x/text/transform"
import "strings"
import "io"
import "os"
import "bytes"

func main() {
KconvFwrite() // ファイル書き込み
KconvFread() // ファイル読み出し
KconvToBuffer() // バッファに書き込み
KconvFromBuffer() // バッファから読み出し
}

// ファイル書き込み
func KconvFwrite() {
s := "漢字です" // UTF8
f, _ := os.Create("EUC.txt")
r := strings.NewReader(s)
w := transform.NewWriter(f, japanese.EUCJP.NewEncoder()) // Encoder->f
io.Copy(w, r) // r -> w(->Encoder->f)
f.Close()
}

// ファイル読み出し
func KconvFread() {
f, _ := os.Open("EUC.txt")
b := new(bytes.Buffer)
r := transform.NewReader(f, japanese.EUCJP.NewDecoder()) // f -> Decoder
io.Copy(b, r) // (f->Decoder)->b
fmt.Println(b.String())
f.Close()
}

// バッファに書き込み
func KconvToBuffer() {
s := "漢字です" // UTF8
b := new(bytes.Buffer)
r := strings.NewReader(s)
w := transform.NewWriter(b, japanese.EUCJP.NewEncoder()) // Encoder->f
io.Copy(w, r) // r -> w(->Encoder->f)

st := b.String()
for i := 0; i < len(st); i++ {
fmt.Println(st[i])
}
fmt.Println(b.String())

}

// バッファから読み出し
func KconvFromBuffer() {
str_bytes := []byte{180, 193, 187, 250, 164, 199, 164, 185}
s := bytes.NewBuffer(str_bytes).String() // "漢字です" in EUC

sr := strings.NewReader(s)
b := new(bytes.Buffer)
r := transform.NewReader(sr, japanese.EUCJP.NewDecoder()) // sr -> Decoder
io.Copy(b, r) // (sr->Decoder)->b
fmt.Println(b.String())
}

マルチバイト文字の数を数える

こちらが詳しいです。 len()だとbyteカウント、[]runeに変換するとutf-8カウント。

1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
s := "日本語"
fmt.Println(len(s)) // => 9
fmt.Println(len([]rune(s))) // => 3
}

マルチバイト文字列の最後の1文字を削除する

1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
s := "日本語"
sc := []rune(s)
fmt.Println(string(sc[:(len(sc) - 1)])) // => "日本"
}

https://ashitani.jp/golangtips/tips_string.html#string_Split