Golang的`exec.Command`函数是否将单引号参数视为特殊字符?

huangapple go评论73阅读模式
英文:

Golang 'exec.Command' treat single quote parameter special?

问题

我正在参考这篇帖子如何执行具有未知参数的系统命令?在我的Ubuntu shell上运行一个jq命令。
以下是我尝试的代码:

import (
    "fmt"
    "os/exec"
    "sync"
    "strings"
)

func exeCmd(cmd string, wg *sync.WaitGroup) {
    fmt.Println("command is ",cmd)
    // splitting head => g++ parts => rest of the command
    parts := strings.Fields(cmd)
    head := parts[0]
    parts = parts[1:len(parts)]
  
    out, err := exec.Command(head,parts...).Output()
    if err != nil {
      fmt.Printf("%s", err)
    }
    fmt.Printf("%s", out)
    wg.Done() // Need to signal to waitgroup that this goroutine is done
}

func main() {
    wg := new(sync.WaitGroup)
    wg.Add(1)

    x := []string{"jq '(.data.legacyCollection.collectionsPage.stream.edges|map({node:(.node|{url,firstPublished,headline:{default:.headline.default},summary})})) as $edges|{data:{legacyCollection:{collectionsPage:{stream:{$edges}}}}}' long-response.json > short-response.json"}

    exeCmd(x[0], wg)

    wg.Wait()
}

输出如下,看起来命令被正确识别,但是shell返回了退出状态3,表示"没有这个进程"?

command is  jq '(.data.legacyCollection.collectionsPage.stream.edges|map({node:(.node|{url,firstPublished,headline:{default:.headline.default},summary})})) as $edges|{data:{legacyCollection:{collectionsPage:{stream:{$edges}}}}}' long-response.json > short-respsonse.json exit status 3

有人可以帮忙解决这个问题吗?
我想要一个能够包装和运行bash命令行的go函数,就像我在Linux shell上执行的方式一样。
PS:我在Linux shell上粘贴上述的jq命令可以正常工作。

尝试了其他方法:删除了我jq命令中的单引号,我的命令被执行并得到了我期望的输出-一个解析后的JSON文件,但是我仍然得到了退出状态2,有人可以解释一下吗?

  1. 为什么我的命令行中的单引号会影响G解析命令?
  2. 为什么在我的shell命令完成后我仍然得到退出状态2?
英文:

I am refer to the post How to execute system command with unknown arguments? to run a jq command on my ubuntu shell.
Below is the code I tried

import (
    "fmt"
    "os/exec"
    "sync"
    "strings"
)

func exeCmd(cmd string, wg *sync.WaitGroup) {
    fmt.Println("command is ",cmd)
    // splitting head => g++ parts => rest of the command
    parts := strings.Fields(cmd)
    head := parts[0]
    parts = parts[1:len(parts)]
  
    out, err := exec.Command(head,parts...).Output()
    if err != nil {
      fmt.Printf("%s", err)
    }
    fmt.Printf("%s", out)
    wg.Done() // Need to signal to waitgroup that this goroutine is done
  }

func main() {
    wg := new(sync.WaitGroup)
    wg.Add(1)

    x := []string{"jq '(.data.legacyCollection.collectionsPage.stream.edges|map({node:(.node|{url,firstPublished,headline:{default:.headline.default},summary})})) as $edges|{data:{legacyCollection:{collectionsPage:{stream:{$edges}}}}}' long-response.json > short-response.json"}

    exeCmd(x[0], wg)

    wg.Wait()
}

The output is as below, seems like the commans is correctly detected but shell returns exit status 3 which is "no such process" ?

command is  jq '(.data.legacyCollection.collectionsPage.stream.edges|map({node:(.node|{url,firstPublished,headline:{default:.headline.default},summary})})) as $edges|{data:{legacyCollection:{collectionsPage:{stream:{$edges}}}}}' long-response.json > short-repsonse.json exit status 3

Anyone can help on this ?
What I want is a go function that can wrapper and run bash command line the same way as I do on Linux shell
PS: the jq command I tried above works pretty well when I paste it on my Linux shell

Tried somethine else: deleted the single quote in my jq command and my command got executed with output I expect - a parsed json file
but still, I got a exist status 2 , anyone can explain

  1. why the single quote in my command line affects how G parse the command ?
  2. why I still go exist 2 after my shell commands complete?

答案1

得分: 2

程序执行的是jq命令,而不是shell命令。jq命令无法理解传递给命令的shell语法(引号和I/O重定向)。

使用以下代码运行命令,并将stdout重定向到short-response.json。

cmd := exec.Command("jq",
    "(.data.legacyCollection.collectionsPage.stream.edges|map({node:(.node|{url,firstPublished,headline:{default:.headline.default},summary})})) as $edges|{data:{legacyCollection:{collectionsPage:{stream:{$edges}}}}}",
    "long-response.json")
f, err := os.Create("short-response.json")
if err != nil {
    log.Fatal(err)
}
defer f.Close()
cmd.Stdout = f  // 将stdout设置为short-response.json
err = cmd.Run()
if err != nil {
    log.Fatal(err)
}
英文:

The program executes the jq command, not a shell. The jq command does not understand the shell syntax passed to the command (the quotes and I/O redirection).

Use the following code to run the command with stdout redirected to short-response.json.

cmd := exec.Command("jq",
	"(.data.legacyCollection.collectionsPage.stream.edges|map({node:(.node|{url,firstPublished,headline:{default:.headline.default},summary})})) as $edges|{data:{legacyCollection:{collectionsPage:{stream:{$edges}}}}}",
	"long-response.json")
f, err := os.Create("short-response.json")
if err != nil {
	log.Fatal(err)
}
defer f.Close()
cmd.Stdout = f  // set stdout to short-response.json
err = cmd.Run()
if err != nil {
	log.Fatal(err)
}

huangapple
  • 本文由 发表于 2022年5月13日 06:00:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/72222499.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定