当传递的参数是先前 运行 exec 的输出时,为什么 os/exec 命令无法按预期工作?

Why does os/exec command not work as expected when passed argument is the output of previously run exec?

我正在尝试使用 golang 在浏览器上打开给定的 URL。当我使用此代码时,它按预期工作并在浏览器中打开给定的 URL:

func main() {
    url := "https://google.com"

    fmt.Printf(url)

    cmd := exec.Command("open", url)

    var out bytes.Buffer
    var stderr bytes.Buffer
    cmd.Stdout = &out
    cmd.Stderr = &stderr

    err := cmd.Run()
    
    if err != nil {
        fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
    }
}

输出(打开浏览器):

~/workspace/go/so ❯ go run main.go
https://google.com%

但是当我使用 exec.Command("echo", "https://google.com") 的输出作为第二个 exec.Command 调用的参数时,程序 returns 出现如下错误:

func main() {
    output, err := exec.Command("echo", "https://google.com").Output()

    if err != nil {
        fmt.Println(err)
    }

    url := string(output)

    fmt.Printf(url)

    cmd := exec.Command("open", url)

    var out bytes.Buffer
    var stderr bytes.Buffer
    cmd.Stdout = &out
    cmd.Stderr = &stderr

    err = cmd.Run()
    
    if err != nil {
        fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
    }
}

输出(错误中URL后面有当前目录路径):

~/workspace/go/so ❯ go run main.go
https://google.com
exit status 1: The file /Users/kadir/workspace/go/so/https:/google.com
 does not exist.

我在第二个代码块中做错了什么?


我的 go 版本是 1.17go.mod 文件是这样的:

module so

go 1.17

require github.com/urfave/cli/v2 v2.3.0

require (
    github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
    github.com/russross/blackfriday/v2 v2.1.0 // indirect
    github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
)

正如@JimB 所指出的,在命令输出的末尾有一个隐含的换行符。

最好使用 fmt %q 动词来确保输出没有恶意字符:

 fmt.Printf("%q\n", url)  // "https://google.com\n"

因此,请在源头解决此问题,使用 echo -n 取消换行符:

output, err := exec.Command("echo", "-n", "https://google.com").Output()

或在接收端:

url = strings.TrimSpace(url)