从带有参数的字符串运行命令

Raf*_*tro 7 go

我试着用go来运行一个命令.该命令是一个字符串.

package main

import (
    "log"
    "os"
    "os/exec"
    "strings"

    "github.com/davecgh/go-spew/spew"
)

func main() {
    commandToRun := `echo $HOME`

    log.Printf("Running %s\n", commandToRun)

    args := strings.Fields(commandToRun)
    spew.Dump(args[1:len(args)])
    command := exec.Command(args[0], args[1:len(args)]...)
    command.Stdout = os.Stdout
    command.Stdin = os.Stdin
    command.Stderr = os.Stderr
    err := command.Run()

    if err != nil {
        log.Printf("Command finished with error: %v", err)
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

2018/11/14 09:41:22 Running echo $HOME
([]string) (len=1 cap=1) {
 (string) (len=5) "$HOME"
}
$HOME
Run Code Online (Sandbox Code Playgroud)

我想拥有的是:

2018/11/14 09:41:22 Running echo $HOME
([]string) (len=1 cap=1) {
 (string) (len=5) "$HOME"
}
/home/whatever
Run Code Online (Sandbox Code Playgroud)

看起来像是以某种方式消毒字符串.所以$HOME没有扩大.是否有任何方法可以像运行shell一样运行字符串?

这是重要的部分.理想情况下,我想在当前shell中从字符串转换为类型.

编辑:下面的示例解决了最简单的情况,但没有涵盖"运行字符串完全像在shell中键入的那样"部分.

如果我切换到expandenv:

commandToRun := os.ExpandEnv(`echo "$HOME"`)
Run Code Online (Sandbox Code Playgroud)

我明白了:

2018/11/14 11:45:44 Running echo "/Users/rafael"
([]string) (len=1 cap=1) {
 (string) (len=15) "\"/home/whatever\""
}
"/home/whatever"
Run Code Online (Sandbox Code Playgroud)

我在shell中得到的是:

$ > echo "$HOME"
/home/whatever
Run Code Online (Sandbox Code Playgroud)

没有引号.

这接近我想要的但不完全正确.

Fli*_*mzy 5

$HOME(以及所有其他env变量)由shell扩展.你没有执行shell,因此它们不会被扩展.

你需要直接在go中查找env变量,例如:

command := exec.Command("echo", os.Getenv("HOME"))
Run Code Online (Sandbox Code Playgroud)

或这个:

commandToRun := os.ExpandEnv("echo $HOME")
command := exec.Command(strings.Fields(commandToRun)...)
Run Code Online (Sandbox Code Playgroud)

请注意,如果$HOME扩展为包含空格的字符串,则此最后一种方法将不起作用,因此os.Getenv对于此用例,该方法通常更安全/更首选.


noa*_*amt 3

在执行命令之前,您可以使用以下命令主动扩展字符串中的所有环境变量os.ExpandEnv

os.ExpandEnv("echo $HOME")
Run Code Online (Sandbox Code Playgroud)

来自文档

ExpandEnv 根据当前环境变量的值替换字符串中的 ${var} 或 $var。对未定义变量的引用将替换为空字符串。