英文:
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
调用的参数时,程序返回以下错误:
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.
在第二个代码块中,我做错了什么?
英文:
I'm trying to open the given URL on the browser using golang. When I use this code, it works as expected and opens the given URL in the browser:
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())
}
}
outputs (opens the browser):
~/workspace/go/so ❯ go run main.go
https://google.com%
But when I use the output of exec.Command("echo", "https://google.com")
as the argument of the second exec.Command
call then program returns an error as below:
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())
}
}
output (there is current directory path as a behind URL in the error):
~/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.
What am I doing wrong in the second code block?
my go version is 1.17 and go.mod
file is this:
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
)
答案1
得分: 2
如@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)
英文:
As @JimB noted there's an implicitly newline at the end of the command output.
It's a good practice to use the fmt
%q
verb to ensure output does not have rogue characters:
fmt.Printf("%q\n", url) // "https://google.com\n"
So fix this either at the source, using echo -n
to suppress the newline:
output, err := exec.Command("echo", "-n", "https://google.com").Output()
or on the receiving end:
url = strings.TrimSpace(url)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论