第14章 テキスト処理

文字列の基本

Go言語における「文字列の基本」は、プログラミングにおいて非常に重要な部分です。Goでの文字列操作にはいくつかの基本的な概念が含まれます。以下に、これらの概念に関する具体的な事例を示します。


文字列の操作

文字列の操作には、結合、分割、比較などが含まれます。

package main

import (
    "fmt"
    "strings"
)

func main() {
	// 文字列の結合
    str1 := "Hello"
    str2 := "World"
    combined := str1 + " " + str2
    fmt.Println(combined) // 出力: Hello World

    // 文字列の分割
    str3 := "a,b,c"
    parts := strings.Split(str3, ",")
    fmt.Println(parts) // 出力: [a b c]

    // 文字列の比較
    str4 := "Go"
    str5 := "Go"
    fmt.Println(str4 == str5) // 出力: true
}


文字列とバイトスライス

文字列はバイトのスライスとして表されることがよくあります。

func main() {
    str := "Hello Go"
    bytes := []byte(str)
    fmt.Println(bytes) // 出力: [72 101 108 108 111 32 71 111]
    strFromBytes := string(bytes)
    fmt.Println(strFromBytes) // 出力: Hello Go
}


UnicodeとUTF-8の処理
func main() {
    str := "Hello, Go!"
    for i := 0; i < len(str); i++ {
        fmt.Printf("Char at position %d: %c\n", i, str[i])
    }
}


部分文字列の取得
func main() {
    str := "Hello, Go!"
    substring := str[7:]
    fmt.Println(substring) // 出力: Go!
}


文字列の検索
func main() {
    str := "Hello, Go!"
    fmt.Println(strings.Contains(str, "Go")) // 出力: true
    fmt.Println(strings.Index(str, "Go"))    // 出力: 7
}


文字列の置換
func main() {
    str := "Hello, Go!"
    newStr := strings.Replace(str, "Go", "Golang", 1)
    fmt.Println(newStr) // 出力: Hello, Golang!
}


文字列のトリミング
func main() {
    str := "   Hello, Go!   "
    trimmed := strings.TrimSpace(str)
    fmt.Println(trimmed) // 出力: Hello, Go!
}


ケース変換
func main() {
    str := "Hello, Go!"
    fmt.Println(strings.ToUpper(str)) // 出力: HELLO, GO!
    fmt.Println(strings.ToLower(str)) // 出力: hello, go!
}


正規表現

Go言語における「正規表現」の処理は、テキストのパターンマッチングやデータの抽出に非常に役立ちます。Goのregexpパッケージを使用することで、複雑な文字列パターンを簡単に処理できます。以下に、正規表現の基本的な使い方に関する具体的な事例を示します。


正規表現のコンパイル

Goでは、正規表現を使用する前に、まずそれを「コンパイル」する必要があります。これは、正規表現のパターンを解析し、後で使用するためのオブジェクトを生成するプロセスです。

package main

import (
    "fmt"
    "regexp"
)

func main() {
    pattern := `hello`
    re, err := regexp.Compile(pattern)
    if err != nil {
        fmt.Println("Error compiling regex:", err)
        return
    }

    str := "hello world"
    match := re.MatchString(str)
    fmt.Println("Match:", match) // 出力: Match: true
}


パターンマッチング

コンパイルした正規表現を使用して、文字列が特定のパターンに一致するかどうかを確認できます。

match := re.MatchString("goodbye world")
fmt.Println("Match:", match) // 出力: Match: false


抽出と置換

正規表現を使用して、文字列から特定のパターンに一致する部分を抽出したり、一致する部分を別の文字列で置換したりすることができます。

// 抽出
emailPattern := `\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b`
reEmail, _ := regexp.Compile(emailPattern)

str := "My email is example@example.com"
emails := reEmail.FindAllString(str, -1)
fmt.Println("Emails:", emails) // 出力: Emails: [example@example.com]

// 置換
replaced := reEmail.ReplaceAllString(str, "[REDACTED]")
fmt.Println(replaced) // 出力: My email is [REDACTED]


文字列のフォーマットと解析

Go言語における「文字列のフォーマットと解析」は、プログラムでのデータの表示や解析において重要な役割を果たします。以下に、文字列のフォーマットと解析に関する具体的な事例を示します。


文字列のフォーマット

Go言語では、fmtパッケージのSprintf関数を用いて文字列をフォーマットすることができます。

package main

import (
    "fmt"
    "time"
)

func main() {
    name := "Alice"
    age := 25
    currentDate := time.Now()

    formattedStr := fmt.Sprintf("My name is %s and I am %d years old. Today's date is %s.", name, age, currentDate.Format("2006-01-02"))
    fmt.Println(formattedStr)
}


文字列の解析

fmtパッケージのSscanf関数を使用すると、フォーマットされた文字列からデータを抽出できます。

package main

import "fmt"

func main() {
    data := "100,200,300"
    var a, b, c int
    n, err := fmt.Sscanf(data, "%d,%d,%d", &a, &b, &c)

    if err != nil {
        fmt.Println("Error:", err)
    }
    fmt.Printf("Parsed %d items: a = %d, b = %d, c = %d\n", n, a, b, c)
}


日付と時刻の解析

Go言語では、timeパッケージを使用して文字列から日付と時刻を解析することができます。

package main

import (
    "fmt"
    "time"
)

func main() {
    dateStr := "2021-03-14"
    parsedDate, err := time.Parse("2006-01-02", dateStr)

    if err != nil {
        fmt.Println("Error parsing date:", err)
    } else {
        fmt.Println("Parsed Date:", parsedDate)
    }
}


数値のフォーマット

数値を特定のフォーマット(例えば、固定小数点数、指数表示など)で文字列に変換する方法も重要です。

value := 12345.6789
formatted := fmt.Sprintf("Fixed point: %.2f", value)
fmt.Println(formatted) // 出力: Fixed point: 12345.68


JSONとの相互変換

Go言語において、encoding/jsonパッケージを使用してJSONデータを解析(Unmarshal)し、またGoのデータ構造をJSONに変換(Marshal)することが一般的です。

// JSONデータの解析
type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

jsonData := `{"name": "Alice", "age": 25}`
var person Person
json.Unmarshal([]byte(jsonData), &person)
fmt.Printf("Name: %s, Age: %d\n", person.Name, person.Age)

// Goデータ構造からJSONへの変換
person := Person{Name: "Bob", Age: 30}
jsonBytes, _ := json.Marshal(person)
fmt.Println(string(jsonBytes)) // 出力: {"name":"Bob","age":30}


練習問題1.

与えられた文字列"Go is an open-source programming language"から次の操作を行ってください。

  1. 文字列を空白で分割してスライスに格納しなさい。
  2. スライス内の各単語を大文字に変換しなさい。
  3. 最終的な単語のスライスを出力しなさい。
package main

import (
    "fmt"
    "strings"
)

func main() {
    str := "Go is an open-source programming language"
    // ここにコードを記述
}


練習問題2.

与えられた文字列"Email: example@example.com"から正規表現を使用して、Eメールアドレスを抽出し出力してください。

package main

import (
    "fmt"
    "regexp"
)

func main() {
    str := "Email: example@example.com"
    // ここにコードを記述
}


練習問題3.

与えられたJSON文字列{"name": "Alice", "age": 30}をGoの構造体に変換し、名前と年齢を出力してください。

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    jsonData := `{"name": "Alice", "age": 30}`
    // ここにコードを記述
}