ホームページ  >  記事  >  バックエンド開発  >  Go を使用したコマンドライン ツール: データのパイプ処理

Go を使用したコマンドライン ツール: データのパイプ処理

Barbara Streisand
Barbara Streisandオリジナル
2024-09-25 06:28:01462ブラウズ

Command-Line Tools with Go: Piping Data

Unix は、コマンドは 1 つのことを実行し、それをうまく実行する必要があるという哲学を提唱していることでよく知られています。

高度なデータ処理と変換操作は、多くの場合、シェル パイプ オペレーターを使用してコマンドを連鎖させ、一方の出力がもう一方の入力となり、データを操作および変換して目的の結果を達成することができます。

例:

# Sort file names.
ls | sort

# Count files.
ls -l | count -l

# Print out unique file extensions.
#  1. List all files that have extensions
#  2. Transform the data (discard everything but extensions)
#  3. Sort the list (data must be sorted to identify duplicates)
#  4. Filter out duplicates
#  5. Browse the results
ls *.* | sed 's/.*\.//' | sort | uniq | less

Go を使用すると、プログラマーはデータを処理するための効率的でパフォーマンスの高いコマンドを作成できます。これについては、次のスニペットで触れます。

出力に行番号を追加する

パイプ操作で使用できるコマンドの本質は、stdin から読み取り、stdout に書き込むことです。

add-line-numbers.go

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {

    // Buffered input that splits input on lines.
    input := bufio.NewScanner(os.Stdin)

    // Buffered output.
    output := bufio.NewWriter(os.Stdout)

    lineNo := 0

    // Scan until EOF (no more input).
    for input.Scan() {
        text := input.Text()
        lineNo++
        s := fmt.Sprintf("%03d %s\n", lineNo, text)

        // It would be simpler to just use fmt.Println,
        // but want to emphasize piping stdin to stdout
        // explicitly.
        // Intentionally ignoring return values.
        _, _ = output.WriteString(s)

    }

    // Always explicitly flush remaining buffered output.
    _ = output.Flush()
}

この例では、stdin から一度に 1 行を読み取り、各行に行番号を接頭辞として付けて stdout に書き戻します。ここでは、プログラム ファイル自体を入力として使用し、番号付き出力を生成します。

$ cat add-line-numbers.go | go run add-line-numbers.go
001 package main
002 
003 import (
004     "bufio"
005     "fmt"
006     "os"
007 )
008 
009 func main() {
010 
011     // Buffered input that splits input on lines.
012     input := bufio.NewScanner(os.Stdin)
013 
014     // Buffered output.
015     output := bufio.NewWriter(os.Stdout)
016 
017     lineNo := 0
018 
019     // Scan until EOF (no more input).
020     for input.Scan() {
021         text := input.Text()
022         lineNo++
023         s := fmt.Sprintf("%03d %s\n", lineNo, text)
024 
025         // It would be simpler to just use fmt.Println,
026         // but want to emphasize piping stdin to stdout
027         // explicitly.
028         // Intentionally ignoring return values.
029         _, _ = output.WriteString(s)
030 
031     }
032 
033     // Always explicitly flush remaining buffered output.
034     _ = output.Flush()
035 
036 }

Base64エンコード入力

この例では、stdin から一度に 1 行を読み取り、base64 でエンコードして、stdout に書き戻します。

package main

import (
    "bufio"
    "encoding/base64"
    "os"
)

func main() {

    // Buffered input that splits input on lines.
    input := bufio.NewScanner(os.Stdin)

    // Base64 Encoder/writer.
    encoder := base64.NewEncoder(
        base64.StdEncoding,
        os.Stdout)

    // Scan until EOF (no more input).
    for input.Scan() {
        bytes := input.Bytes()
        _, _ = encoder.Write(bytes)
        _, _ = encoder.Write([]byte{'\n'})
    }

    // Close the encoder and ensure it flushes remaining output
    _ = encoder.Close()
}

スキャナは改行文字 (n) を返さずに分割するため、各行を書き込んだ後に明示的に改行を記述する必要があります。

$ cat base64-encode.go | go run base64-encode.go
cGFja2FnZSBtYWluCgppbXBvcnQgKAoJImJ1ZmlvIgoJImVuY29kaW5nL2Jhc2U2NCIKCSJvcyIKKQoKZnVuYyBtYWluKCkgewoKCS8vIEJ1ZmZlcmVkIGlucHV0IHRoYXQgc3BsaXRzIGlucHV0IG9uIGxpbmVzLgoJaW5wdXQgOj0gYnVmaW8uTmV3U2Nhbm5lcihvcy5TdGRpbikKCgkvLyBCYXNlNjQgRW5jb2Rlci93cml0ZXIuCgllbmNvZGVyIDo9IGJhc2U2NC5OZXdFbmNvZGVyKAoJCWJhc2U2NC5TdGRFbmNvZGluZywKCQlvcy5TdGRvdXQpCgoJLy8gU2NhbiB1bnRpbCBFT0YgKG5vIG1vcmUgaW5wdXQpLgoJZm9yIGlucHV0LlNjYW4oKSB7CgkJYnl0ZXMgOj0gaW5wdXQuQnl0ZXMoKQoJCV8sIF8gPSBlbmNvZGVyLldyaXRlKGJ5dGVzKQoJCV8sIF8gPSBlbmNvZGVyLldyaXRlKFtdYnl0ZXsnXG4nfSkKCX0KCgkvLyBDbG9zZSB0aGUgZW5jb2RlciBhbmQgZW5zdXJlIGl0IGZsdXNoZXMgcmVtYWluaW5nIG91dHB1dAoJXyA9IGVuY29kZXIuQ2xvc2UoKQp9Cg==

エンコードされた結果をシステムの Base64 コマンド (Linux および MacOS) にパイプしてデコードすることで、テキストが正しくエンコードされたことを確認できます。

$ cat base64-encode.go | go run base64-encode.go | base64 -D
package main

import (
    "bufio"
    "encoding/base64"
    "os"
)

func main() {

    // Buffered input that splits input on lines.
    input := bufio.NewScanner(os.Stdin)

    // Base64 Encoder/writer.
    encoder := base64.NewEncoder(
        base64.StdEncoding,
        os.Stdout)

    // Scan until EOF (no more input).
    for input.Scan() {
        bytes := input.Bytes()
        _, _ = encoder.Write(bytes)
        _, _ = encoder.Write([]byte{'\n'})
    }

    // Close the encoder and ensure it flushes remaining output
    _ = encoder.Close()
}

この投稿は、コマンド ライン ツールの作成に役立つ Go の標準ライブラリ機能について私が書いた短い入門ガイド (Go for CLI Apps and Tools) からの抜粋です。

以上がGo を使用したコマンドライン ツール: データのパイプ処理の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。