为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
摇曳的蔷薇 2023-05-08 16:08:01
我正在尝试使用 go 运行命令。命令在一个字符串中。package mainimport (    "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看起来 go 正在以某种方式清理字符串。所以$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没有引号。这接近我想要的,但不完全是。
查看完整描述

4 回答

?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

$HOME(以及所有其他环境变量)由 shell 扩展。您没有执行 shell,因此它们不会扩展。


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


command := exec.Command("echo", os.Getenv("HOME"))

或这个:


commandToRun := os.ExpandEnv("echo $HOME")

args := strings.Fields(commandToRun)

command := exec.Command(args[0], args[1:]...)

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


查看完整回答
反对 回复 2023-05-08
?
PIPIONE

TA贡献1829条经验 获得超9个赞

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

os.ExpandEnv("echo $HOME")

从文档:

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


查看完整回答
反对 回复 2023-05-08
?
明月笑刀无情

TA贡献1828条经验 获得超4个赞

如果您想获得 的输出$ echo $HOME,您需要的最少代码是

fmt.Println(os.Getenv("HOME"))

不需要更多了。

  • 如果你使用os.ExpandEnv("echo $HOME"),那么首先$HOMEvar 将被扩展然后它会给你一个像这样的字符串echo /home/<user>

  • 如果您使用command := exec.Command("echo", os.Getenv("HOME")), 那么它将被解析为command := exec.Command("echo", "/home/<user>")finally 这将给出输出/home/<user>

  • 如果你使用

    commandToRun := os.ExpandEnv("echo $HOME") command := exec.Command(strings.Fields(commandToRun)...)

    那么它将像以前的案例一样处理。

所以更好的方法是只使用fmt.Println(os.Getenv("HOME")).


查看完整回答
反对 回复 2023-05-08
?
ITMISS

TA贡献1871条经验 获得超8个赞

您需要运行一个 shell。在 Go 中扩展它似乎很愚蠢并且容易出错,因为你有一个可以运行的 shell。

commandToRun := `echo "$SHELL"`
cmd := exec.Command("/bin/sh", "-c", commandToRun)
command := exec.Command(args[0], args[1:len(args)]...)
command.Stdout = os.Stdout
command.Stdin = os.Stdin
command.Stderr = os.Stderr
err := command.Run()

这应该适用于任何 POSIX 系统。今天的孩子们在他们的命令行中加入了很多 bashisms,因此您可以将其切换为运行,/bin/bash但请注意,这在 FreeBSD 或其他一些系统(其他 BSD 及其派生系统)上不起作用。


查看完整回答
反对 回复 2023-05-08
  • 4 回答
  • 0 关注
  • 111 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信