kurumi-bioの雑記帳

プログラミング、パソコン、ペット、 犬、お出かけ

初心者のGo言語 -42- <IsAbs,Join,Match,Split>

こんにちは、kurumi-bioです。
第2回目のpathパッケージ(標準ライブラリー)の学習です。

前回の記事

kurumi-bio.hatenablog.com

APIリファレンス(過去記事の一覧)

kurumi-bio.hatenablog.com

環境

  • Windows
    OSバージョン:Windows11 Home 22H2
    Go言語のバージョン:go version go1.20.3 windows/amd64
  • Linux
    OSバージョン:openSUSE Leap 15.4
    Go言語のバージョン:go version go1.20.3 linux/amd64

IsAbs関数

func IsAbs(path string) bool

関数の説明 IsAbs はパスが絶対パスかどうかを報告します。

package main

import (
    "fmt"
    "path"
)

func printIsAbs(pathString string) {
    fmt.Printf("[%s] -> [%t]\n", pathString, path.IsAbs(pathString))
}

func main() {
    fmt.Println("\nドライブ名付き")
    printIsAbs("c:/test/test.bat")
    fmt.Println("\nドライブ名無し")
    printIsAbs("/test/test.bat")
    fmt.Println("\nフォルダ名から開始")
    printIsAbs("test/test.bat")
    fmt.Println("\nファイルのみ")
    printIsAbs("test.bat")
    fmt.Println("\n直下のファイル")
    printIsAbs("./test.bat")
    fmt.Println("\n/が二つ")
    printIsAbs("//test/test.bat")
}

コードの説明 色々な形式で記載したパスをpath.IsAbs関数に渡した結果を出力します。

◆実行結果(Windows)

◆実行結果(Linux)

実行結果の説明 WindowsLinuxで同じ結果になりました。
/から始まっていれば絶対パスと判断されます。
ドライブ名から始まっていても絶対パスと判断されませんでした。

Join関数

func Join(elem ...string) string

関数の説明 Join は、任意の数のパス要素をスラッシュで区切って 1 つのパスに結合します。空の要素は無視されます。結果はクリーンになりました。ただし、引数リストが空であるか、そのすべての要素が空の場合、Join は空の文字列を返します。

package main

import (
    "fmt"
    "path"
)

func printJoin(n ...string) {
    fmt.Printf("%s\n", path.Join(n...))
}

func main() {
    printJoin("A", "B")

    fmt.Println("\nドライブ名付き")
    printJoin("C:", "test", "test.go")
    printJoin("C:", "test", "..", "test.go")
    printJoin("C:", "test", "/", "test.go")

    fmt.Println("\nドライブ名無し")
    printJoin("/", "test", "test.go")
    printJoin("/", "test", "..", "test.go")
    printJoin("/", "test", "/", "test.go")
}

コードの説明 色々な形式で記載したパス要素をpath.Join関数に渡した結果を出力します。

◆実行結果(Windows)

◆実行結果(Linux)

実行結果の説明 WindowsLinuxで同じ結果になりました。 ドライブ名もパス要素として結合されました。 パス要素の".."を指定するとその前のパス要素が無効になり一階層上になって結合されました。

Match関数

func Match(pattern, name string) (matched bool, err error)

関数の説明 Match は、名前がシェル パターンと一致するかどうかを報告します。パターンの構文は次のとおりです。

pattern:
    { term } 
term:
    '*'         matches any sequence of non-/ characters
    '?'         matches any single non-/ character
    '[' [ '^' ] { character-range } ']'
                character class (must be non-empty)
    c           matches character c (c != '*', '?', '\\', '[')
    '\\' c      matches character c

character-range:
    c           matches character c (c != '\\', '-', ']')
    '\\' c      matches character c
    lo '-' hi   matches character c for lo <= c <= hi

一致には、部分文字列だけでなく、名前全体と一致するパターンが必要です。パターンの形式が不正な場合に返される可能性のある唯一のエラーは ErrBadPattern です

package main

import (
    "fmt"
    "path"
)

func printMatch(p, n string) {
    b, e := path.Match(p, n)
    if e != nil {
        fmt.Printf("pattern=[%s] / name=[%s] / Match Error : %v\n", p, n, e)
    } else {
        fmt.Printf("pattern=[%s] / name=[%s] / matched=[%t]\n", p, n, b)
    }
}
func main() {
    fmt.Println("\n/以外の任意の文字列")
    printMatch("a*", "abc")
    printMatch("a*", "a*c")
    printMatch("a*", "a/c")
    printMatch("b*", "abc")

    fmt.Println("\n/以外の任意の文字列")
    printMatch("a?", "abc")
    printMatch("a??", "abc")

    fmt.Println("\n'範囲指定")
    printMatch("a[1-3]c", "a2c")
    printMatch("a[1-3]c", "a4c")
    printMatch("[a-c][x-z]", "by")
    printMatch("[a-c][x-z]", "dw")

    fmt.Println("\n'文字")
    printMatch("abc", "abc")
    printMatch("abc", "123")
    printMatch("a\\c", "a\\c")
    printMatch("a-c", "a-c")
    printMatch("a[c", "a[c")

    fmt.Println("\n'エスケープ文字")
    printMatch("a\\\\c", "a\\c")
    printMatch("a\\-c", "a-c")
    printMatch("a\\[c", "a[c")
}

コードの説明 色々なパターンをpath.Match関数に渡した結果を出力します。

◆実行結果(Windows)

◆実行結果(Linux)

実行結果の説明 WindowsLinuxで同じ結果になりました。
/[は、\\エスケープすることでパターンに使用することができました。

Split関数

func Split(path string) (dir, file string)

関数の説明 Split は、最後のスラッシュの直後でパスを分割し、ディレクトリとファイル名のコンポーネントに分割します。パスにスラッシュがない場合、Split は空のディレクトリとパスに設定されたファイルを返します。戻り値には、path = dir+file というプロパティがあります。

package main

import (
    "fmt"
    "path"
)

func printSplit(p string) {
    d, f := path.Split(p)
    fmt.Printf("path=[%s] / dir=[%s] / file=[%s]\n", p, d, f)
}
func main() {

    fmt.Println("\nドライブ名付き、パス文字列が\\")
    printSplit("C:\\")
    printSplit("C:\\test.go")
    printSplit("C:\\temp\\test.go")
    printSplit("C:\\temp\\folder1\\test.go")

    fmt.Println("\nドライブ名付き")
    printSplit("C:/")
    printSplit("C:/test.go")
    printSplit("C:/temp/test.go")
    printSplit("C:/temp/folder1/test.go")

    fmt.Println("\nドライブ名無し")
    printSplit("/")
    printSplit("/test.go")
    printSplit("/temp/test.go")
    printSplit("/temp/folder1/test.go")
    printSplit("test.go")
}

コードの説明 色々な形式で記載したパス要素をpath.Split関数に渡した結果を出力します。

◆実行結果(Windows)

◆実行結果(Linux)

実行結果の説明 WindowsLinuxで同じ結果になりました。
階層文字は、/(スラッシュ)で指定する必要があります。 ドライブ名が含まれてても正常に分割できました。

最後までご覧いただきありがとうございます