Julio
Julio

Reputation: 2523

Goland reading liner per line output of a command

I would like to read an output command line per line. For this I use the StdoutPipe method and the bufio library:

package main

import (
        "encoding/json"
        "fmt"
        "log"
        "os/exec"
        "bufio"
)


func main() {
        cmd := exec.Command("printf", "{\"Name\": \"Bob\", \"Age\": 1}\n%.0s", "{1..5}")
        stdout, err := cmd.StdoutPipe()
        if err != nil {
                log.Fatal(err)
        }
        scanner := bufio.NewScanner(stdout)
        if err := cmd.Start(); err != nil {
                log.Fatal(err)
        }
        var person struct {
                Name string
                Age  int
        }
        for scanner.Scan() {
                if err := json.Unmarshal([]byte(scanner.Text()), &person); err != nil {
                        log.Fatal(err)
                } else {
                        fmt.Printf("%s is %d years old\n", person.Name, person.Age)
                }
        }
        if err := cmd.Wait(); err != nil {
                log.Fatal(err)
        }
}

I should obtain 5 lines:

$ printf "{\"Name\": \"Bob\", \"Age\": 1}\n%.0s" {1..5}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}
{"Name": "Bob", "Age": 1}

The point is that I only get the first line. I am quite new on Goand I guess the usage of the StdoutPipe is incorrect.

Upvotes: 1

Views: 225

Answers (1)

Ainar-G
Ainar-G

Reputation: 36189

{1..5} is expanded to 1 2 3 4 5 by the shell, so you must do it yourself:

cmd := exec.Command("printf", `{"Name": "Bob", "Age": %s}\n`, `1`, `2`) // etc.

Also note the use of raw strings, its much more convenient than constantly escaping everything. And on a related note, instead of []byte(scanner.Text()) you should really use scanner.Bytes().

Upvotes: 1

Related Questions