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)
}
}
输出是:
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"
我在外壳中得到的是:
$ > echo "$HOME"
/home/whatever
没有引号。
这接近我想要的,但不完全是。
解决方案
$HOME
(以及所有其他环境变量)由 shell 扩展。您没有执行外壳程序,因此它们不会被扩展。
您需要直接在 go 中查找 env 变量,例如:
command := exec.Command("echo", os.Getenv("HOME"))
或这个:
commandToRun := os.ExpandEnv("echo $HOME")
command := exec.Command(strings.Fields(commandToRun)...)
$HOME
请注意,如果扩展为包含空格的字符串,则最后一种方法将不起作用,因此os.Getenv
对于此用例,该方法通常更安全/首选。
推荐阅读
- java - 在尝试使复合类方法对另一个包类可见时避免违反 SOLID 原则
- cassandra - 如何在没有分区键的情况下使用 ORDER_BY 搜索记录
- html - IE/Edge 不考虑绝对底部
- javascript - 有没有办法将事件监听器添加到类中?
- ios - UIAlertController 没有立即显示
- spring - 页面加载时的 Spring MVC 表单验证
- h2o - 可以为 h2o.save_model() 设置文件名(而不是简单地使用 model_id 值)?
- javascript - 谷歌地图标记没有显示 javascript
- node.js - Amazon Web Services 上的连接被拒绝
- c# - 了解为什么在 Bot Builder Framework 示例中似乎进行了 3 次翻译:MultiLingualBot