bitfield/script

repository·master·Indexed 27 days ago

https://github.com/bitfield/script

A Go library that provides a pipeline-based API for system administration and data processing, designed to make these tasks as easy as writing shell scripts. It includes sources for reading files, stdin, and HTTP requests; filters for data transformation, regex matching, and JQ queries; and sinks for outputting to files or stdout. The library also supports a go-script interpreter for executing one-liners and .goscript files.

Tokens
3.7K
Snippets
7
Records
23
Agent score
42%

What's inside bitfield/script

  1. Use the `go-script` interpreter for one-liners and `.goscript` files

    master

    You can run script one-liners directly via a bash interpreter or create .goscript files using a shebang line. This allows you to execute pipeline logic without a full Go build process.

    One-liner example:

    cat file.txt | ./goscript.sh -c 'script.Stdin().Column(1).Freq().First(10).Stdout()'

    .goscript file example:

    #!/tmp/goscript.sh
    script.Stdin().Column(1).Freq().First(10).Stdout()
    cat file.txt | ./goscript.sh -c 'script.Stdin().Column(1).Freq().First(10).Stdout()'
  2. Handle errors in pipelines

    master

    When a stage in the pipeline encounters an error (e.g., a non-2xx HTTP status code), subsequent stages become no-ops. You can retrieve the error by calling the .Error() method or by using a sink method like .String() or .Stdout() which returns an error value.

    _, err := script.Do(req).Stdout()
    if err != nil {
    	log.Fatal(err)
    }
  3. Execute external subprocesses

    master
    Run external commands using script.Exec(command). Note that Exec runs concurrently and streams output as it is produced. To run a command repeatedly for each line in the pipeline, use ExecForEach with Go template syntax ({{.}}) to inject the data.
  4. Query JSON data with JQ

    master

    If your pipeline contains JSON data, you can use the .JQ(query) method to interrogate it using standard JQ syntax.

    data, err := script.Do(req).JQ(".[0] | {message: .commit.message, name: .commit.committer.name}").String()
  5. Process data from Stdin, Args, or HTTP

    master

    The library allows you to start a pipeline from various sources:

    • script.Stdin(): Read from standard input.
    • script.Args(): Read from command-line arguments.
    • script.Get(url): Perform a GET request.
    • script.Echo(data): Start a pipeline with specific data.
  6. Customize HTTP requests with custom clients or headers

    master

    For advanced HTTP needs, use script.NewPipe() to configure a custom http.Client, or use script.Do(req) to execute a pre-configured *http.Request.

    // Using a custom HTTP client
    script.NewPipe().WithHTTPClient(&http.Client{
    	Timeout: 10 * time.Second,
    }).Get("https://example.com").Stdout()
    
    // Using a custom request with headers
    req, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
    req.Header.Add("Authorization", "Bearer "+token)
    script.Do(req).Stdout()
  7. Filter and transform data

    master

    You can transform data using built-in methods or custom logic:

    • FilterLine(func): Apply an arbitrary Go function to every line.
    • Filter(func): Apply a custom function that takes an io.Reader and io.Writer.
    • FilterScan(func): Scan input line by line using a custom function.
    // Transform lines using a function
    script.Stdin().Match("Error").FilterLine(strings.ToUpper).Stdout()
    
    // Custom Filter with Reader/Writer
    script.Echo("hello world").Filter(func (r io.Reader, w io.Writer) error {
    	n, err := io.Copy(w, r)
    	fmt.Fprintf(w, "\nfiltered %d bytes\n", n)
    	return err
    }).Stdout()
    
    // Line-by-line scanning
    script.Echo("a\nb\nc").FilterScan(func(line string, w io.Writer) {
    	fmt.Fprintf(w, "scanned line: %q\n", line)
    }).Stdout()
  8. Map Unix commands to `script` operations

    master

    If you are transitioning from shell scripting, use this mapping to find the equivalent script method for common Unix utilities:

    Unix / shellscript equivalent
    [ -f FILE ]IfExists
    >WriteFile
    >>AppendFile
    $*Args
    base64DecodeBase64 / EncodeBase64
    basenameBasename
    catFile / Concat
    curlDo / Get / Post
    cutColumn
    dirnameDirname
    echoEcho
    findFindFiles
    grepMatch / MatchRegexp
    grep -vReject / RejectRegexp
    headFirst
    jqJQ
    lsListFiles
    sedReplace / ReplaceRegexp
    sha256sumHash / HashSums
    tailLast
    teeTee
    uniq -cFreq
    wc -lCountLines
    xargsExecForEach