我试着用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)
    }
}
输出是:
2018/11/14 09:41:22 Running echo $HOME
([]string) (len=1 cap=1) {
 (string) (len=5) "$HOME"
}
$HOME
我想拥有的是:
2018/11/14 09:41:22 Running echo $HOME
([]string) (len=1 cap=1) {
 (string) (len=5) "$HOME"
}
/home/whatever
看起来像是以某种方式消毒字符串.所以$HOME没有扩大.是否有任何方法可以像运行shell一样运行字符串?
这是重要的部分.理想情况下,我想在当前shell中从字符串转换为类型.
编辑:下面的示例解决了最简单的情况,但没有涵盖"运行字符串完全像在shell中键入的那样"部分.
如果我切换到expandenv:
commandToRun := os.ExpandEnv(`echo "$HOME"`)
我明白了:
2018/11/14 11:45:44 Running echo "/Users/rafael"
([]string) (len=1 cap=1) {
 (string) (len=15) "\"/home/whatever\""
}
"/home/whatever"
我在shell中得到的是:
$ > echo "$HOME"
/home/whatever
没有引号.
这接近我想要的但不完全正确.
$HOME(以及所有其他env变量)由shell扩展.你没有执行shell,因此它们不会被扩展.
你需要直接在go中查找env变量,例如:
command := exec.Command("echo", os.Getenv("HOME"))
或这个:
commandToRun := os.ExpandEnv("echo $HOME")
command := exec.Command(strings.Fields(commandToRun)...)
请注意,如果$HOME扩展为包含空格的字符串,则此最后一种方法将不起作用,因此os.Getenv对于此用例,该方法通常更安全/更首选.
在执行命令之前,您可以使用以下命令主动扩展字符串中的所有环境变量os.ExpandEnv:
os.ExpandEnv("echo $HOME")
来自文档:
ExpandEnv 根据当前环境变量的值替换字符串中的 ${var} 或 $var。对未定义变量的引用将替换为空字符串。
| 归档时间: | 
 | 
| 查看次数: | 187 次 | 
| 最近记录: |